使用WebUploader實(shí)現(xiàn)分片斷點(diǎn)上傳文件功能(二)
寫(xiě)在前面:
這幾天,有去研究一下WebUploader上傳文件,前面的博客有記錄下使用WebUploader簡(jiǎn)單上傳文件的例子,今天就把分片斷點(diǎn)上傳的例子也記錄下吧,在博客園中,也查看了一些資料,基本上后臺(tái)處理數(shù)據(jù)都是用的Servlet,或者是SpringMVC,由于最近的項(xiàng)目一直都是Struts2,所以這里就用Struts2中的action來(lái)對(duì)數(shù)據(jù)進(jìn)行處理,達(dá)到分片上傳文件的效果。
1.什么是分片上傳?
顧名思義,就是把文件分成一片片,即讓一個(gè)文件,分割成好幾個(gè)小文件,然后再上傳。這樣做的好處是便于上傳大文件。
2.分片上傳大致思路:
1.前臺(tái)頁(yè)面,選擇文件,點(diǎn)擊按鈕進(jìn)行上傳。
2.WebUploader將上傳的文件,分割成指定的個(gè)數(shù),挨個(gè)發(fā)送到服務(wù)端后臺(tái)。
3.服務(wù)器接收分割后的小文件,并存儲(chǔ)到臨時(shí)文件夾下
4.服務(wù)器接收分割后的小文件完畢后,前臺(tái)頁(yè)面執(zhí)行上傳成功函數(shù)。
5.在上傳成功函數(shù)中,發(fā)送請(qǐng)求到服務(wù)器,請(qǐng)求合并小文件為一個(gè)整體的文件。
6.服務(wù)器后臺(tái)對(duì)文件進(jìn)行合并操作,合并完成后刪除存儲(chǔ)小文件的臨時(shí)文件。
了解了分片上傳的大致過(guò)程,下面直接上demo吧。
前臺(tái)頁(yè)面:
<%@ 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)站的訪問(wèn)跟路徑
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(){}來(lái)進(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)鍵 如果開(kāi)啟了分片上傳 并不限制同時(shí)上傳的數(shù)目 會(huì)導(dǎo)致后臺(tái)接受的分片錯(cuò)亂 比如按正常的分片第一片應(yīng)該是開(kāi)頭
但接收的可能就變成第三片從而順序錯(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)來(lái)的時(shí)候
uploader.on('fileQueued', function (file) {
//重新選擇文件 進(jìn)行清空
$("#fileList").html("");
//具體邏輯根據(jù)項(xiàng)目需求來(lái)寫(xiě) 這里知識(shí)簡(jiǎn)單的舉個(gè)例子寫(xiě)下
$one = $("<div id='"+file.id+"'>"+file.name+"</div>");
$two = $("<div id='state'>等待上傳......</div>");
$("#fileList").append($one);
$("#fileList").append($two);
});
// 文件上傳過(guò)程中創(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">開(kāi)始上傳</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再去寫(xiě)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è)就跟普通的保存文件沒(méi)啥區(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);//文件追加寫(xiě)入
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)所有追加寫(xiě)入都寫(xiě)完 才可以關(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ǔ)充說(shuō)明下,后臺(tái)只是接收了一些簡(jiǎn)單的參數(shù)而已,而從前臺(tái)WebUploader傳遞過(guò)來(lái)的參數(shù)當(dāng)然不止上面那幾個(gè)了,所以,可以學(xué)會(huì)用F12調(diào)試模式,進(jìn)行查看發(fā)送的請(qǐng)求,以及相關(guān)的請(qǐng)求參數(shù),這里就不多說(shuō)了
運(yùn)行截圖:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 關(guān)于webuploader插件使用過(guò)程遇到的小問(wèn)題
- 推薦三款不錯(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顯示問(wèn)題解決方法
- webuploader分片上傳的實(shí)現(xiàn)代碼(前后端分離)
- php + WebUploader實(shí)現(xiàn)圖片批量上傳功能
相關(guān)文章
Java工程編碼格式由GBK轉(zhuǎn)化成utf-8的具體實(shí)現(xiàn)
在寫(xiě)項(xiàng)目的過(guò)程中我發(fā)現(xiàn)有的地方編碼格式被設(shè)置成了 gbk 如果用eclipse等工具直接改回utf-8編碼格式則會(huì)出現(xiàn)亂碼,所以本文給大家介紹了Java工程編碼格式由GBK轉(zhuǎn)化成utf-8的具體實(shí)現(xiàn),感興趣的朋友可以參考下2024-05-05
Spring實(shí)現(xiàn)源碼下載編譯及導(dǎo)入IDEA過(guò)程圖解
這篇文章主要介紹了Spring實(shí)現(xiàn)源碼下載編譯及導(dǎo)入IDEA,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
實(shí)現(xiàn)java文章點(diǎn)擊量記錄實(shí)例
這篇文章主要為大家介紹了實(shí)現(xiàn)java文章點(diǎn)擊量記錄實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
Java幾個(gè)實(shí)例帶你進(jìn)階升華上篇
與其明天開(kāi)始,不如現(xiàn)在行動(dòng),本文為你帶來(lái)幾個(gè)Java書(shū)寫(xiě)的實(shí)際案例,對(duì)鞏固編程的基礎(chǔ)能力很有幫助,快來(lái)一起往下看看吧2022-03-03
Springboot實(shí)現(xiàn)根據(jù)用戶ID切換動(dòng)態(tài)數(shù)據(jù)源
在很多具體應(yīng)用場(chǎng)景中,我們需要用到動(dòng)態(tài)數(shù)據(jù)源的情況,比如多租戶的場(chǎng)景,系統(tǒng)登錄時(shí)需要根據(jù)用戶信息切換到用戶對(duì)應(yīng)的數(shù)據(jù)庫(kù)。這篇文章主要介紹了SpringBoot根據(jù)用戶ID實(shí)現(xiàn)切換動(dòng)態(tài)數(shù)據(jù)源的示例代碼,感興趣的可以了解一下2021-12-12
java list,set,map,數(shù)組間的相互轉(zhuǎn)換詳解
這篇文章主要介紹了java list,set,map,數(shù)組間的相互轉(zhuǎn)換詳解的相關(guān)資料,這里附有實(shí)例代碼,具有參考價(jià)值,需要的朋友可以參考下2017-01-01
SpringBoot3?Web編程開(kāi)發(fā)的工程搭建攔截器及測(cè)試工具示例
這篇文章主要介紹了SpringBoot3?Web編程開(kāi)發(fā)的工程搭建攔截器及測(cè)試工具示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
Springboot文件上傳功能簡(jiǎn)單測(cè)試
這篇文章主要介紹了Springboot文件上傳功能簡(jiǎn)單測(cè)試,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
使用javax.validation.constraints對(duì)請(qǐng)求體進(jìn)行統(tǒng)一校驗(yàn)
這篇文章主要介紹了使用javax.validation.constraints對(duì)請(qǐng)求體進(jìn)行統(tǒng)一校驗(yàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07

