WebUploaderJava大文件分片上传.docx
- 文档编号:25346647
- 上传时间:2023-06-07
- 格式:DOCX
- 页数:16
- 大小:353.49KB
WebUploaderJava大文件分片上传.docx
《WebUploaderJava大文件分片上传.docx》由会员分享,可在线阅读,更多相关《WebUploaderJava大文件分片上传.docx(16页珍藏版)》请在冰豆网上搜索。
WebUploaderJava大文件分片上传
Web大文件分片上传
Web环境中大文件上传不能再用form表单一次上传了,这样效率太低;
我在不断尝试SpringMVC环境下分片接受文件,最终失败;原因目测是 SpringMVC、Struts框架是不支持HTML5方式上传的(这类框架只能支持Form表单方式的文件上传,或者FLash)
那我们可以使用Servlet和SpringMVC结合集成方式实现大文件分片上传;
一、来看看我们的web.xml的配置
很明显两个servlet,上面一个配置的是SpringMVC的入口,下面servlet是视频上传;
他们俩的url-pattern不能冲突;
二、先来看看WebUploader的前端代码
以下是代码:
<%@pagelanguage="java"contentType="text/html;charset=UTF-8"
pageEncoding="UTF-8"%>
DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http:
//www.w3.org/TR/html4/loose.dtd">
href="${pageContext.request.scheme}:
//${pageContext.request.serverName}:
${pageContext.request.serverPort}${pageContext.request.contextPath}/">
HelloWorld!
20px20px20px0;">
varuploader=WebUploader.create({
//swf文件路径
swf:
'webuploader/Uploader.swf',
//文件接收服务端。
server:
'UploadVideoServlet',
//选择文件的按钮。
可选。
//内部根据当前运行是创建,可能是input元素,也可能是flash.
pick:
'#picker',
threads:
2,
chunked:
true,//分片处理
chunkSize:
5*1024*1024,//每片5M
threads:
1,//上传并发数。
允许同时最大上传进程数。
//不压缩image,默认如果是jpeg,文件上传前会压缩一把再上传!
resize:
false
});
//当有文件被添加进队列的时候
uploader.on('fileQueued',function(file){
//alert(123);
$("#thelist").append(
'
+'
+'
});
uploader.on('uploadSuccess',function(file){
alert(uploader.options.formData.guid);
alert(Math.ceil(file.size/(5*1024*1024)));
alert(file.name);
$('#'+file.id).find('p.state').text('已上传');
$.post("UploadSuccessServlet",{"guid":
uploader.options.formData.guid,chunks:
Math.ceil(file.size/(5*1024*1024)),fileName:
file.name},
function(data){
},"json");
});
uploader.on('uploadError',function(file){
$('#'+file.id).find('p.state').text('上传出错');
});
uploader.on('uploadComplete',function(file){
$('#'+file.id).find('.progress').fadeOut();
});
$("#btnSync").on('click',function(){
if($(this).hasClass('disabled')){
returnfalse;
}
uploader.options.formData.guid=Math.random();
uploader.upload();
});
三、servlet分片获取
分片就是前段将文件分成多个,每片都是一个post请求,有多少片就请求多少次servlet;
我们以获取的guid为文件名建立临时文件夹,以chunk(片序号)为文件名来存储文件;
以下为代码:
packagecom.airodlcx;
importjava.io.File;
importjava.io.IOException;
importjava.lang.reflect.InvocationTargetException;
importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importmons.beanutils.BeanUtils;
importmons.fileupload.FileItem;
importmons.fileupload.FileUploadException;
importmons.fileupload.disk.DiskFileItemFactory;
importmons.fileupload.servlet.ServletFileUpload;
importmons.io.FileUtils;
/**
*ServletimplementationclassUploadVideo
*/
publicclassUploadVideoServletextendsHttpServlet{
privatestaticfinallongserialVersionUID=1L;
/**
*@seeHttpServlet#HttpServlet()
*/
publicUploadVideoServlet(){
super();
//TODOAuto-generatedconstructorstub
}
/**
*@seeHttpServlet#doGet(HttpServletRequestrequest,HttpServletResponse
*response)
*/
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
//TODOAuto-generatedmethodstub
response.getWriter().append("Servedat:
").append(request.getContextPath());
}
/**
*@seeHttpServlet#doPost(HttpServletRequestrequest,HttpServletResponse
*response)
*/
protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
Stringpath=request.getSession().getServletContext().getRealPath("/upload");
System.out.println(path);
DiskFileItemFactoryfactory=newDiskFileItemFactory();
//2、创建一个文件上传解析器
ServletFileUploadupload=newServletFileUpload(factory);
//解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
//3、判断提交上来的数据是否是上传表单的数据
if(!
ServletFileUpload.isMultipartContent(request)){
return;
}
//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List
List
try{
list=upload.parseRequest(request);
}catch(FileUploadExceptione){
e.printStackTrace();
}
HashMap
System.out.println("-------------------------------------------------------------");
for(FileItemitem:
list){
if(item.isFormField()){
/**
*表单数据
*/
Stringname=item.getFieldName();
//解决普通输入项的数据的中文乱码问题
Stringvalue=item.getString("UTF-8");
//value=newString(value.getBytes("iso8859-1"),"UTF-8");
System.out.println(name+"="+value);
map.put(name,value);//放入map集合
}else{
/**
*文件上传
*/
FilefileParent=newFile(path+"/"+map.get("guid"));//以guid创建临时文件夹
System.out.println(fileParent.getPath());
if(!
fileParent.exists()){
fileParent.mkdir();
}
Stringfilename=item.getName();
if(filename==null||filename.trim().equals("")){
continue;
}
//注意:
不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:
//c:
\a\b\1.txt,而有些只是单纯的文件名,如:
1.txt
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
filename=filename.substring(filename.lastIndexOf("\\")+1);
//创建文件
Filefile;
if(map.get("chunks")!
=null){
file=newFile(fileParent,map.get("chunk"));
}else{
file=newFile(fileParent,"0");
}
//copy
FileUtils.copyInputStreamToFile(item.getInputStream(),file);
}
}
}
}
四、前端WebUploader上传完毕触发uploadSuccess事件
uploader.on('uploadSuccess',function(file){
alert(uploader.options.formData.guid);
alert(Math.ceil(file.size/(5*1024*1024)));
alert(file.name);
$('#'+file.id).find('p.state').text('已上传');
$.post("UploadSuccessServlet",{"guid":
uploader.options.formData.guid,chunks:
Math.ceil(file.size/(5*1024*1024)),fileName:
file.name},
function(data){
},"json");
});
请求servlet去合并之前的guid文件夹下的分片文件,post请求中的分片数量可以用来校验,获取的分片是否正确,也可以前端传递md5,后台校验;
五、后台获取的log
图:
上传的GUID命名的文件夹
图:
文件夹下的分片文件
每个分割线包住的地方是一个servlet请求,最后在success请求的servlet是进行文件校验并合并文件即可;代码见下:
6、java文件合并
代码见下:
protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
Stringpath=request.getSession().getServletContext().getRealPath("/upload");
Stringguid=request.getParameter("guid");
intchunks=Integer.parseInt(request.getParameter("chunks"));
StringfileName=request.getParameter("fileName");
System.out.println("start...!
guid="+guid+";chunks="+chunks+";fileName="+fileName);
/**
*进行文件合并
*/
Filefile=newFile(path+"/"+guid);
/**
*判断分片数量是否正确
*/
if(file.list().length!
=chunks){
return;
}
newFile("F:
//upload"+"/"+guid).mkdir();
/**
*进行文件合并
*/
FilenewFile=newFile("F:
//upload"+"/"+guid+"/"+fileName);
FileOutputStreamoutputStream=newFileOutputStream(newFile,true);//文件追加写入
byte[]byt=newbyte[10*1024*1024];
intlen;
FileInputStreamtemp=null;//分片文件
for(inti=0;i temp=newFileInputStream(newFile(path+"/"+guid+"/"+i)); while((len=temp.read(byt))! =-1){ System.out.println(len); outputStream.write(byt,0,len); } } /** *当所有追加写入都写完才可以关闭流 */ outputStream.close(); temp.close(); System.out.println("success! guid="+guid+";chunks="+chunks+";fileName="+fileName); } 文件夹以guid命名,数据库储存guid的名字,后期数据移动,只需要更改前端显示的路径; 在这里up遇到一个问题,上传报错: IOException: 磁盘空间不足;然而我上传的磁盘还有20G;原因是系统盘空间不足;up重装系统就好了; 注: 1、进度条的显示就很容易了 引入bootstrap的进度条 0%;">