最近项目上用到文件分片上传,于是找到了百度的一个开源前端控件webuploader。 于是尝试使用。

下载下来后,它提供的服务器端示例代码是php版的,那么Java版的呢?

其实,上传文件都是按照rfc1867标注来的, 只是分段上传需要在前端多做点事情。分段上传原理其实就是在前端使用JavaScript对文件进行分割成不同小块,然后每次ajax请求就post一小块,直到全部收到为止。

但是,为了确保后端能判断文件是否完整的收到,需要得知当前是第几块,一共多少块,每个分段的大小是多少(前后端同学约定好吧),webuploader是有把这些参数传给后端, 但文档里没说明参数名称啊,看了其他后端example,并且自己做了实验才知道。


参数:
name 文件名
chunks 一共有多少分片
chunk 当前分片是第几片file 文件对象
重点来了:后端接收到这些参数应该怎么处理? 之前看过一个example ,是把每个分片文件都暂时存起来,命名为 文件名.part_1, 文件名.part_2, 文件名.part_3...文件名part_n, 每次都从1到总分片个数(注:这个值就是chunks的值),
遍历这些文件是否存在.如果都存在说明全部上传完成了,则再循环一遍,把所有分段都合并到一个文件里. 这么做虽然是可以,但是如果文件很大, 最后一个分片到达的时候响应可能会很慢,效率低下.
那么应该怎么解决呢?考虑了一会, 联想到,以前使用迅雷之类的工具下载,除下载下来的文件以外,还会有一个额外的文件用来存放下载之类的信息.
受到这个启发, 我决定这么设计: 每当第n个分片到达时(注:n的值其实就是收到的chunk的值), 使用java的随机文件读写类RandomAccessFile, 定位到 n*分片大小(注:每个分片大小跟前端约定好的)的位置
long offset = chunkSize * param.getChunk();
//定位到该分片的偏移量
accessTmpFile.seek(offset);

然后写入分片内容.
//写入该分片数据
accessTmpFile.write(param.getFileItem().get()); 同时,往一个配置文件,暂且命名为 文件名.conf 设置长度为chunks的值, 也就是分片个数.
accessConfFile.setLength(param.getChunks());

然后往第n个位置写入一个Byte.MAX_VALUE,
accessConfFile.seek(param.getChunk());
accessConfFile.write(Byte.MAX_VALUE);
因为写入的单位就是字节,所以我这么操作就相当于在第n个字节里写入全1的状态. 然后检查,从0到chunks开始每一个字节进行与操作, 一旦到第n个字节发现与运算的结果不是全1(Byte.MAX_VALUE)那么就说明这个文件的第n个部分没有传输完成. 
如果conf文件0到chunks的位置全部进行与运算的最后结果还是Byte.MAX_VALUE,那么就说明这个文件已经传输完成,该干嘛就干嘛..
//completeList 检查是否全部完成,如果数组里是否全部都是(全部分片都成功上传)
byte[] completeList = FileUtils.readFileToByteArray(confFile);
byte isComplete = Byte.MAX_VALUE;
for (int i = 0; i < completeList.length && isComplete==Byte.MAX_VALUE; i++) {
//与运算, 如果有部分没有完成则 isComplete 不是 Byte.MAX_VALUE
isComplete = (byte)(isComplete & completeList[i]);
System.out.println(prefix + "check part " + i + " complete?:" + completeList[i]);
} if (isComplete == Byte.MAX_VALUE) {
System.out.println(prefix + "upload complete !!");
}
其实还有另一种想法是,前端传来该文件的md5码,然后后端每次接收到都算一次md5码,如果一致则说明上传成功,但是效率应该也不够上面的好,于是没实现. 谁有更好的想法可以留言哈.
 

现在可以开始例子:
在前端webuploader source的examples/image-upload/upload.js 中可以看到
        // 实例化
uploader = WebUploader.create({
pick: {
id: '#filePicker',
label: '点击选择图片'
},
formData: {
uid: 123
},
dnd: '#dndArea',
paste: '#uploader',
swf: '../../dist/Uploader.swf',
chunked: false,
chunkSize: 512 * 1024,
server: '../../server/fileupload.php',
// runtimeOrder: 'flash', // accept: {
// title: 'Images',
// extensions: 'gif,jpg,jpeg,bmp,png',
// mimeTypes: 'image/*'
// }, // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。
disableGlobalDnd: true,
fileNumLimit: 300,
fileSizeLimit: 200 * 1024 * 1024, // 200 M
fileSingleSizeLimit: 50 * 1024 * 1024 // 50 M
});
chunked 被设置为false, 改为true就可以分片上传了。
chunkSize这个后端需要用到,所以前后端需要保持一致。
server改成java后端自己定义的上传文件接口的地址,我这里根据后端例子改成了“http://127.0.0.1:8080/file/test-upload2”
////此处已删除一些旧的不可运行的代码, 代码请看分割线下面

----------------------------------------2018 分割线--------------------------------------------------

上面的代码太久远了, 从之前那公司项目里扣下来的, 忘记去掉某些不需要的类了` 在此抱歉

新整理的代码放到github上了

https://github.com/ThomasHuang025/webuploader-spring-example

记录: 百度webuploader 分片文件上传java服务器端(spring mvc)示例的优化的更多相关文章

  1. Ceph RGW服务 使用s3 java sdk 分片文件上传API 报‘SignatureDoesNotMatch’ 异常的定位及规避方案

    import java.io.File;   import com.amazonaws.AmazonClientException; import com.amazonaws.auth.profile ...

  2. Baidu WebUploader 前端文件上传组件的使用

    简介 WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件.在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流I ...

  3. silverlight漂亮的文件上传进度显示原理及示例

    silverlight漂亮的文件上传进度显示原理及示例 作者:chenxumi 出处:博客园  2009/11/27 13:37:11 阅读 1219  次 概述:在网站根目录web.config里配 ...

  4. WebUploader分片断点上传文件(二)

    写在前面: 这几天,有去研究一下WebUploader上传文件,前面的博客有记录下使用WebUploader简单上传文件的例子,今天就把分片断点上传的例子也记录下吧,在博客园中,也查看了一些资料,基本 ...

  5. Asp.Net Core 2.0 WebUploader FastDfs 文件上传 分段上传

    功能点: 1. 使用.net core 2.0 实现文件上传 2. 使用webuploader实现单文件,多文件上传 3. 使用webuploader实现大文件的分段上传. 4. 使用webuploa ...

  6. 前后端分离跨服务器文件上传-Java SpringMVC版

    近来工作上不上特别忙,加上对后台java了解一点,所以就抽时间,写了一个java版本的前后端分离的跨服务器文件上传功能,包括前后端代码. 一.Tomcat服务器部分 1.Tomcat服务器 单独复制一 ...

  7. IOS 多文件上传 Java web端(后台) 使用List<MultipartFile> 接收出现的问题

    先上正确的示例: 主要是设置我们的request的content-type为multipart/form-data NSDictionary *param = @{@"assignee&qu ...

  8. 文件上传(java web)

    文件上传: 对表单的要求: * method="post" * enctype="multipart/form-data" * 表单中需要添加文件表单项:< ...

  9. Python实现对百度云的文件上传

    环境准备 python3.6 PyCharm 2017.1.3 Windows环境 框架搭建 selenium3.6 安装方法: pip install selenium 实现步骤: 一.步骤分析 1 ...

随机推荐

  1. border,border-width不支持百分比

    1.border-width不支持百分比 原因:不会因为设备大就按比例变大 同样的,outline,box-shadow,text-shadow也不支持百分比 也就是border不支持百分比 2.bo ...

  2. easyui datagrid复选框控制单选

    使用easyui datagrid的时候,由于对数据表格操作太多,并且有单选和多选功能因此采用复选框.但是在单选的状态,使用CheckOnSelect和singleselect时发现,页面有明显延迟, ...

  3. luoguT30204 偷上网

    \(n=1\) 时特判四角,其余时刻圆的面积和必小于正方形面积,随机点出来判断就行了. stm 随机算法-- #include <iostream> #include <cstdli ...

  4. 了解Windows Server以及Hyper-V许可模式

    在2015年11月,微软宣布对Windows Server 2016以及Hyper-V的许可模式进行重大变更,并于2016年第三季度正式生效,Windows Server 2016标准版及数据中心版的 ...

  5. JS一个非常经典的问题:在遍历数组时对DOM监听事件,索引值将始终等于遍历结束后的值

    一个简单的Tab选项卡点击事件. <style type="text/css"> ul{padding:0;margin:0;} .tab{width:400px;} ...

  6. 利用js阻止表单提交

    (1) return false <form name="loginForm" action="login.aspx" method="post ...

  7. PostgreSQL drop database 显示会话没有关闭 [已解决]

    错误重现 有时候需要删除某个数据库时,会报如下错误,显示有一个连接正在使用数据库,无法删除 ERROR: database "pilot" is being accessed by ...

  8. 基于单层决策树的AdaBoost算法源码

    基于单层决策树的AdaBoost算法源码 Mian.py # -*- coding: utf-8 -*- # coding: UTF-8 import numpy as np from AdaBoos ...

  9. (转载)CentOS 6.5使用aliyun镜像来源

    (原地址:http://www.linuxidc.com/Linux/2014-09/106675.htm) 当我们把CentOS 6.5安装好以后,可以使用这个脚本来使用国内的阿里云镜像源 #!/b ...

  10. 【HDU 1686 Oulipo】

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...