使用WebUploader實(shí)現(xiàn)分片斷點(diǎn)上傳文件功能(二)
寫在前面:
這幾天,有去研究一下WebUploader上傳文件,前面的博客有記錄下使用WebUploader簡(jiǎn)單上傳文件的例子,今天就把分片斷點(diǎn)上傳的例子也記錄下吧,在博客園中,也查看了一些資料,基本上后臺(tái)處理數(shù)據(jù)都是用的Servlet,或者是SpringMVC,由于最近的項(xiàng)目一直都是Struts2,所以這里就用Struts2中的action來對(duì)數(shù)據(jù)進(jìn)行處理,達(dá)到分片上傳文件的效果。
1.什么是分片上傳?
顧名思義,就是把文件分成一片片,即讓一個(gè)文件,分割成好幾個(gè)小文件,然后再上傳。這樣做的好處是便于上傳大文件。
2.分片上傳大致思路:
1.前臺(tái)頁面,選擇文件,點(diǎn)擊按鈕進(jìn)行上傳。
2.WebUploader將上傳的文件,分割成指定的個(gè)數(shù),挨個(gè)發(fā)送到服務(wù)端后臺(tái)。
3.服務(wù)器接收分割后的小文件,并存儲(chǔ)到臨時(shí)文件夾下
4.服務(wù)器接收分割后的小文件完畢后,前臺(tái)頁面執(zhí)行上傳成功函數(shù)。
5.在上傳成功函數(shù)中,發(fā)送請(qǐng)求到服務(wù)器,請(qǐng)求合并小文件為一個(gè)整體的文件。
6.服務(wù)器后臺(tái)對(duì)文件進(jìn)行合并操作,合并完成后刪除存儲(chǔ)小文件的臨時(shí)文件。
了解了分片上傳的大致過程,下面直接上demo吧。
前臺(tái)頁面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <% String scheme = request.getScheme(); String serverName = request.getServerName(); String contextPath = request.getContextPath(); int port = request.getServerPort(); //網(wǎng)站的訪問跟路徑 String baseURL = scheme + "://" + serverName + ":" + port + contextPath; request.setAttribute("baseURL", baseURL); %> <html> <head> <title>WebUploader文件分片上傳簡(jiǎn)單示例</title> <%--引入css樣式--%> <link href="${baseURL}/webuploader0.1.5/webuploader.css" rel="external nofollow" rel="stylesheet" type="text/css"/> <script src="${baseURL}/ligerui2/jquery/jquery-1.9.0.min.js" type="text/javascript"></script> <%--引入文件上傳插件--%> <script type="text/javascript" src="${baseURL}/webuploader0.1.5/webuploader.min.js"></script> <script type="text/javascript"> $(function(){ /* 對(duì)于uploader的創(chuàng)建,最好等dom元素也就是下面的div創(chuàng)建好之后再創(chuàng)建,因?yàn)槔锩嬗杏玫竭x擇文件按鈕, 不然會(huì)創(chuàng)建報(bào)錯(cuò),這是很容易忽視的地方,故這里放到$(function(){}來進(jìn)行創(chuàng)建*/ var uploader = WebUploader.create({ // swf文件路徑 swf: '${baseURL}/webuploader0.1.5/Uploader.swf', // 文件接收服務(wù)端地址。 server: '${baseURL}/uploadFile2', // [默認(rèn)值:'file'] 設(shè)置文件上傳域的name。 fileVal:'upload', // 選擇文件的按鈕??蛇x。 // 內(nèi)部根據(jù)當(dāng)前運(yùn)行是創(chuàng)建,可能是input元素,也可能是flash. pick: { multiple: false, id: '#filePicker' }, // 上傳并發(fā)數(shù)。允許同時(shí)最大上傳進(jìn)程數(shù)[默認(rèn)值:3] 即上傳文件數(shù) /*這個(gè)是關(guān)鍵 如果開啟了分片上傳 并不限制同時(shí)上傳的數(shù)目 會(huì)導(dǎo)致后臺(tái)接受的分片錯(cuò)亂 比如按正常的分片第一片應(yīng)該是開頭 但接收的可能就變成第三片從而順序錯(cuò)亂 這是由于百度webuploader默認(rèn)允許同時(shí)最大上傳進(jìn)程數(shù)為3個(gè) 所以會(huì)導(dǎo)致接受順序錯(cuò)亂從而重組發(fā)生錯(cuò)誤,故這里設(shè)置為1*/ threads: 1, // 自動(dòng)上傳修改為手動(dòng)上傳 auto: false, //是否要分片處理大文件上傳。 chunked: true, // 如果要分片,分多大一片? 默認(rèn)大小為5M. chunkSize: 5 * 1024 * 1024, // 不壓縮image, 默認(rèn)如果是jpeg,文件上傳前會(huì)壓縮一把再上傳! resize: false, formData: { guid: Math.random() //這里主要用于命名存儲(chǔ)小文件的臨時(shí)文件夾 } }); //當(dāng)有文件添加進(jìn)來的時(shí)候 uploader.on('fileQueued', function (file) { //重新選擇文件 進(jìn)行清空 $("#fileList").html(""); //具體邏輯根據(jù)項(xiàng)目需求來寫 這里知識(shí)簡(jiǎn)單的舉個(gè)例子寫下 $one = $("<div id='"+file.id+"'>"+file.name+"</div>"); $two = $("<div id='state'>等待上傳......</div>"); $("#fileList").append($one); $("#fileList").append($two); }); // 文件上傳過程中創(chuàng)建進(jìn)度條實(shí)時(shí)顯示。 uploader.on('uploadProgress', function (file, percentage) { // 具體邏輯... console.log("uploadProgress===="+percentage); $("#state").text("正在上傳中..."); }); // 文件上傳成功處理。 uploader.on('uploadSuccess', function (file, response) { // 具體邏輯... console.log('upload success...\n'); console.log(uploader.options.formData.guid); console.log(file.name); //合并文件 $.post( "${baseURL}/mergeFile", //發(fā)送到后臺(tái)的參數(shù) { guid: uploader.options.formData.guid, chunks: Math.ceil(file.size / (5 * 1024 * 1024)), fileName: file.name }, function(data){ }); $("#state").text("文件上傳成功啦~~~"); }); // 文件上傳失敗處理。 uploader.on('uploadError', function (file) { // 具體邏輯... }); // 上傳傳完畢,不管成功失敗都會(huì)調(diào)用該事件,主要用于關(guān)閉進(jìn)度條 uploader.on('uploadComplete', function (file) { // 具體邏輯... }); //點(diǎn)擊上傳按鈕觸發(fā)事件 $("#btnClick").click(function(){ uploader.upload(); }); //取消上傳 $("#btnCancel").click(function(){ //邏輯處理.. }); }); </script> </head> <body style="padding:10px"> <div id="layout1"> <div id="uploader-demo"> <div id="fileList" ></div> <div id="filePicker" >選擇文件</div> <button id="btnClick">開始上傳</button> <button id="btnCancel">取消上傳</button> </div> </div> </body> </html>
后臺(tái)action:
/** * Description:com.ims.action * Author: Eleven * Date: 2017/12/26 10:50 */ @Controller("FileAction") public class FileAction { /*用于接收分割請(qǐng)求的每個(gè)小文件的相關(guān)參數(shù)*/ //記得提供對(duì)應(yīng)的get set方法 //上傳文件對(duì)象(和表單type=file的name值一致) private File upload; //文件名 private String uploadFileName; //上傳類型 private String uploadContentType; /** * 以下變量都是public,參數(shù)太多,不想設(shè)為private再去寫get,set方法了, * 就偷個(gè)懶直接用了public了 */ //文件分片序號(hào) public String chunk; public String guid;//合并與分割都有用到 //用于接收發(fā)送合并請(qǐng)求的相關(guān)參數(shù) public String fileName; //文件名 public String chunks; //分割數(shù)量 //當(dāng)進(jìn)行分片上傳文件的時(shí)候,每上傳一個(gè)小文件就會(huì)調(diào)用這個(gè)方法,這個(gè)就跟普通的保存文件沒啥區(qū)別的 public void uploadFile2() throws Exception{ String str = "D:/upload44/divide/"; //文件保存路徑 //保存每個(gè)小文件的路徑 String realPath = str + guid +"/" + chunk; File tmp =new File(realPath); FileUtils.copyFile(upload, tmp); System.out.println("上傳文件"+uploadFileName+",第幾塊:"+chunk+",大?。?+(upload.length()/1024/1024)+"M"); } //文件合并 public void mergeFile() throws Exception{ String path = "D:/upload44/merge/" ; //創(chuàng)建 合并文件夾 new File(path).mkdir(); //創(chuàng)建 合并后的文件 File newFile = new File(path + fileName); if(!newFile.exists()){ newFile.createNewFile(); } FileOutputStream outputStream = new FileOutputStream(newFile, true);//文件追加寫入 byte[] byt = new byte[10 * 1024 * 1024]; int len; FileInputStream temp = null;//分片文件 for (int i = 0; i < Integer.parseInt(chunks); i++) { //"D:/upload44/divide/" + guid + "/" + i 為保存分割后的小文件的路徑 temp = new FileInputStream(new File("D:/upload44/divide/" + guid + "/" + i)); while ((len = temp.read(byt)) != -1) { System.out.println(len); outputStream.write(byt, 0, len); } temp.close(); } //當(dāng)所有追加寫入都寫完 才可以關(guān)閉流 outputStream.close(); //刪除分片文件 String path2 = "D:/upload44/divide/" + guid; FileUtils.deleteDirectory(new File(path2));//刪除目錄下所有的內(nèi)容 System.out.println("success!guid=" + guid + ";chunks=" + chunks + ";fileName=" + fileName); } public File getUpload() { return upload; } public void setUpload(File upload) { this.upload = upload; } public String getUploadFileName() { return uploadFileName; } public void setUploadFileName(String uploadFileName) { this.uploadFileName = uploadFileName; } public String getUploadContentType() { return uploadContentType; } public void setUploadContentType(String uploadContentType) { this.uploadContentType = uploadContentType; } }
struts.xml配置:
<action name="uploadFile2" class="FileAction" method="uploadFile2"> </action> <action name="mergeFile" class="FileAction" method="mergeFile"> </action>
好啦,到這里,一個(gè)簡(jiǎn)單的文件分片斷點(diǎn)上傳就完成了。
對(duì)了補(bǔ)充說明下,后臺(tái)只是接收了一些簡(jiǎn)單的參數(shù)而已,而從前臺(tái)WebUploader傳遞過來的參數(shù)當(dāng)然不止上面那幾個(gè)了,所以,可以學(xué)會(huì)用F12調(diào)試模式,進(jìn)行查看發(fā)送的請(qǐng)求,以及相關(guān)的請(qǐng)求參數(shù),這里就不多說了
運(yùn)行截圖:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 關(guān)于webuploader插件使用過程遇到的小問題
- 推薦三款不錯(cuò)的圖片壓縮上傳插件(webuploader、localResizeIMG4、LUploader)
- 百度多文件異步上傳控件webuploader基本用法解析
- 使用WebUploader實(shí)現(xiàn)上傳文件功能(一)
- 快速掌握jQuery插件WebUploader文件上傳
- webuploader 實(shí)現(xiàn)圖片批量上傳功能附實(shí)例代碼
- webuploader實(shí)現(xiàn)上傳圖片到服務(wù)器功能
- webuploader模態(tài)框ueditor顯示問題解決方法
- webuploader分片上傳的實(shí)現(xiàn)代碼(前后端分離)
- php + WebUploader實(shí)現(xiàn)圖片批量上傳功能
相關(guān)文章
Spring Security 自定義資源服務(wù)器實(shí)踐過程
這篇文章主要介紹了Spring Security 自定義資源服務(wù)器實(shí)踐,我們通過自己搭建的授權(quán)服務(wù)器和資源服務(wù)器,完整體驗(yàn)了OAuth2流程,需要的朋友可以參考下2022-08-08Java設(shè)計(jì)模式之策略模式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
策略模式是對(duì)算法的封裝,把一系列的算法分別封裝到對(duì)應(yīng)的類中,并且這些類實(shí)現(xiàn)相同的接口,相互之間可以替換。接下來通過本文給大家分享Java設(shè)計(jì)模式之策略模式,感興趣的朋友一起看看吧2017-08-08Java必備知識(shí)之位運(yùn)算及常見進(jìn)制解讀
從現(xiàn)代計(jì)算機(jī)中所有的數(shù)據(jù)二進(jìn)制的形式存儲(chǔ)在設(shè)備中。即 0、1 兩種狀態(tài),計(jì)算機(jī)對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行的運(yùn)算(+、-、*、/)都是叫位運(yùn)算,即將符號(hào)位共同參與運(yùn)算的運(yùn)算2021-10-10Java filter中的chain.doFilter使用詳解
這篇文章主要介紹了Java filter中的chain.doFilter使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11使用SpringBoot請(qǐng)求參數(shù)過濾空格
這篇文章主要介紹了使用SpringBoot請(qǐng)求參數(shù)過濾空格的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Maven發(fā)布封裝到中央倉庫時(shí)候報(bào)錯(cuò):no default secret key
這篇文章主要介紹了Maven發(fā)布封裝到中央倉庫時(shí)候報(bào)錯(cuò):no default secret key,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12