您的位置:首页 > 编程语言 > Java开发

chunkupload 文件上传断点续传组件(java) - 正式发布

2016-10-05 10:15 661 查看
chunkupload简介

chunkupload是一款基于java语言的断点续传组件,针对文件上传,非文件下载,集成方便,使用简单。

chunkupload实现如下功能:

· 实现断点续传

· 对于同一个文件,允许多用户同时上传,并且上传的用户越多,上传越快

· 线程安全

· 同一物理机下进程安全

· 文件自动切片,支持合并

· 内存占用小

· 高效稳定,高可用

· 易集成,无第三方依赖

chunkupload只关注文件上传,并没有安全机制,开发者需要自行设计安全控制策略,防范用户上传非法文件,chunkupload默认上传的文件是安全的。

chunkupload功能完备,服务端和客户端无缝衔接,开发者只需关注自身业务和UI展现即可。

为了尽可能提升用户体验,chunkupload在客户端的技术选型有些激进,采用了许多先进的技术,比如:web worker、XMLHttpRequest数据传送进度、FileReader、file slice等,所以对浏览器兼容性会有一定影响,在确定使用chunkupload前请务必仔细斟酌!

chunkupload集成

服务端

chunkupload服务端运行需要JRE7或更高版本,无任何第三方依赖。

1.引用chunkupload.1.0.jar。

2.在项目web.xml中配置chunkupload servlet。

<servlet>
<servlet-name>ChunkUpload</servlet-name>
<servlet-class>com.iyangyuan.chunkupload.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ChunkUpload</servlet-name>
<url-pattern>/chunkupload/*</url-pattern>
</servlet-mapping>


强烈建议将chunkupload servlet配置在安全框架之后(比如shiro),mvc框架之前(如springmvc)。

chunkupload servlet中的拦截路径(url-pattern),如果无特殊需求,无需更改,假如一定要更改,还需要同步更改客户端的配置。

客户端

chunkupload客户端对浏览器的要求比较高,目前已知chrome、firefox浏览器完整支持,360浏览器如果启用webkit内核,应该也没有问题,IE浏览器绝对不支持(想都不要想),其他浏览器未知。

开发者可能会问,为什么兼容性如此捉襟见肘?

chunkupload是新时代的产物,它代表了时代的发展方向,它的价值在于提供最先进的技术示范,而不是沉重的历史包袱。

chunkupload在客户端的实现,无任何第三方依赖,只关注与服务端的逻辑交互,并不干预UI展现,为开发者创造最大的发挥空间。

1.引用dawn.1.0.js,用于在客户端计算文件MD5,dawn.js是chunkupload的一个附属项目,相比未经优化的javascript计算MD5方法,dawn.js将计算效率提升50%左右。

2.引用chunkupload.1.0.js,此乃chunkupload客户端核心库,封装了所有上传所需的逻辑。

chunkupload使用

服务端

服务端需要创建chunkupload.properties配置文件,放置在项目classpath根目录下,也就是大家熟悉的log4j.properties所在目录,配置文件中有如下选项:

· root 文件存储路径,相当于根目录,内部还会有chunkupload创建的目录结构;假如同一台物理机配置多个文件上传容器,此项配置应该设置成统一目录,默认为[/data]。

· fileLockCapacity 文件锁缓存容量,一般设置为2048即可,开发者可根据服务器性能自行调整,默认为2048。

· createFile 文件上传完成后,是否立即合并切片,生成完整文件;强烈建议此配置项设置为false,一般情况下,切片无需合并,就算合并,也不需要立即合并;如果设为true,立即合并文件会占用大量服务器资源,并且会造成客户端长时间等待;合并的速度大约100M/S,视服务器具体性能而定,默认为true。

至此,服务端已经可以正常运作了。

客户端

默认情况下,客户端无需任何配置。

假如开发者更改过chunkupload servlet拦截路径,那么chunkupload.1.0.js中的Block.config.api配置也需要做相应的改动,具体情况需要开发者自行斟酌。

ChunkUpload 类

文件上传核心实现类。

实例化

上传组件初始化需要提供目标文件。

/**

* 实例化ChunkUpload组件

* file 要上传的目标文件对象

*/

var cu = new ChunkUpload(file);


upload 方法

upload 方法用来启动文件上传,通过四个异步回调完成上传交互,无返回值。

cu.upload({
"success": function(block){
/**
* 上传成功回调
*
* block 对象,块对象
*/
},
"error": function(e){
/**
* 上传异常回调
*
* e 字符串,异常信息
*/
},
"md5Progress": function(n){
/**
* 计算文件md5进度回调
*
* n 整型,进度数值
*/
},
"uploadProgress": function(n){
/**
* 上传进度回调
*
* n 整型,进度数值
*/
}
});


abort方法

abort方法用来中断上传,可以在任意阶段任意时刻中断,无返回值。

cu.abort();


Block 类

文件控制类。

实例化

/**

* 初始化块对象

* md5 文件md5,32位

* size 文件大小,字节

*/

var block = new Block(md5, size);


info方法

获取块(文件)信息,返回javascript对象。

block.info();


返回示例:

{

"status": 0,   //业务状态,0表示成功

"data": {  //数据域

"chunks": [  //所有切片信息

{

"md5": "e114c21f7d9f8ad1a8551225c3d085be",   //切片md5

"n": 1  //切片序号

},

{

"md5": "48357caa7607a636e858315e1b0216d5",

"n": 2

},

{

"md5": "a23c6ab7104d2ce4ae3c1624ea7eab55",

"n": 3

},

{

"md5": "3eb29f6241d6fbb35cc715fff2b9ab91",

"n": 4

},

{

"md5": "120ddc96b878a63adcd7835cbac0c95c",

"n": 5

}

],

"chunkNum": 5,   //切片数量

"md5": "f1154ca6fab7f3628927c1268f3570fd",   //文件md5

"state": 1,   //文件状态,1为上传完成

"size": 20879935  //文件长度

}

}


delete方法

删除块(文件) ,无返回值。

block.delete();


chunkupload服务端存储珠玑

任何上传的文件都会在服务端进行切片处理,每个切片4M大小。

通过文件MD5和文件大小,唯一确定一个文件。

目录分散策略,基于开发者自定义的rootpath,文件MD5前6位,每两位作为一级目录,最后以文件MD5+文件长度作为最终目录,所有文件信息均存储在此目录下。

假如文件MD5为[071287fffa974b878732a7a17858be36],长度为[20879935],开发者自定义的rootpath为[/data],那么生成的目录结构为:[/data/07/12/87/071287fffa974b878732a7a17858be3620879935]。

chunkupload存储的关于文件的所有信息,均为二进制文件,并且文件名称固定,具体组织如下图:

<html>
<head>
<title>ChunkUpload 删除文件示例</title>
<meta charset="utf-8">
<meta name="viewport" id="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
<style>
body {
font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body > div {
width: 200px;
margin: 20px auto 0 auto;
}
body > div.form {
color: #686868;
font-size: 15px;
text-align: center;
}
body > div.form > p {
margin: 1em 0 .4em 0;
text-align: left;
}
body > div.form > input {
background-color: transparent;
outline: none;
font-family: inherit;
font-size: inherit;
color: inherit;
}
body > div.form > input:hover {
background-color: #f5f5f5;
}
body > div.form > input.text {
padding: 6px 8px;
border: 1px solid #dcdcdc;
}
body > div.form > input.button {
border: 1px dashed #dcdcdc;
cursor: pointer;
padding: 0 10px;
line-height: 29px;
}
div.info{
width: 400px;
background-color: #f7faff;
border: 1px solid #b2d7ff;
padding: 10px 8px;
}
div.info > p{
margin: 0;
text-align: left;
font-size: 14px;
word-break: break-all;
}
</style>
</head>
<body>
<!-- 表单部分 -->
<div class="form">
<p>文件md5</p>
<input id="md5" class="text" type="text" placeholder="文件md5" />
<p>文件大小(字节)</p>
<input id="size" class="text" type="text" placeholder="文件大小(字节)" />
<p></p>
<input id="execBtn" class="button" type="button" value="删除" />
</div>
<!-- 结果展示 -->
<div class="info">
<p id="text">
</p>
</div>
</body>
<script src="/static/lib/dawn/dawn.js"></script>
<script src="/static/lib/chunkupload/chunkupload.js"></script>
<script>
var execBtn = document.getElementById("execBtn"),
md5 = document.getElementById("md5"),
size = document.getElementById("size"),
text = document.getElementById("text");

execBtn.addEventListener("click", function(e) {
var block = new Block(md5.value, size.value);

block.delete(function(info){
text.innerText = JSON.stringify(info);
},function(status, text){
text.innerText = "哎呀!出错啦," + text;
});
});
</script>
</html>


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: