使用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-08
Java設(shè)計(jì)模式之策略模式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
策略模式是對(duì)算法的封裝,把一系列的算法分別封裝到對(duì)應(yīng)的類中,并且這些類實(shí)現(xiàn)相同的接口,相互之間可以替換。接下來通過本文給大家分享Java設(shè)計(jì)模式之策略模式,感興趣的朋友一起看看吧2017-08-08
Java必備知識(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-10
Java 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-08
Maven發(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

