dnf90版本刷图dnf帕拉丁刷图怎么样

2009年4月 总版技术专家分月排行榜第一
2009年11月 Linux/Unix社区大版内专家分月排行榜第一2009年6月 Linux/Unix社区大版内专家分月排行榜第一2009年4月 C/C++大版内专家分月排行榜第一2009年3月 C/C++大版内专家分月排行榜第一2009年3月 Linux/Unix社区大版内专家分月排行榜第一2009年2月 Linux/Unix社区大版内专家分月排行榜第一
本帖子已过去太久远了,不再提供回复功能。1864人阅读
总结与分享
文件上传在web应用中是比较常见的功能,前段时间做了一个多文件、大文件、多线程文件上传的功能,使用效果还不错,总结分享下。
一、 功能性需求与非功能性需求
要求操作便利,一次选择多个文件进行上传;
支持大文件上传(1G),同时需要保证上传期间用户电脑不出现卡死等体验;
交互友好,能够及时反馈上传的进度;
服务端的安全性,不因上传文件功能导致JVM内存溢出影响其他功能使用;
最大限度利用网络上行带宽,提高上传速度;
二、 设计分析
对于大文件的处理,无论是用户端还是服务端,如果一次性进行读取发送、接收都是不可取,很容易导致内存问题。所以对于大文件上传,采用切块分段上传
从上传的效率来看,利用多线程并发上传能够达到最大效率。
对于大文件切块、多线程上传,需要考虑服务端合并文件的时间点;
三、解决方案:
在HTML5之前的标准是无法支持上面的功能,因此我们需要把功能实现居于H5提供的新特性上面:
1. H5新标准对file标签进行了增强,支持同时选择多个文件
&input type="file" multiple=true onchange="doSomething(this.files)"/&
注意multiple属性,设置为true;
onchange:一般是选择文件确定后的响应事件
this.files:文件对象集合
2. File对象
H5提供的类似java的RandomAccessFile的文件操作对象,其中silce方法允许程序指定文件的起止字节进行读取。利用这个对象,实现对大文件的切分;
3. XMLHttpRequest
这个对象大家应该很熟悉了,属于web2.0的标准,我们最常用的ajax请求底层就是居于此对象。本质上XMLHttpRequest是一个线程对象,因此我们通过创建一定数量的XMLHttpRequest对象,实现多线程并行操作;
4. FormData对象
H5新增对象,可以理解为一个key-value的map,通过把文件的二进制流和业务参数封装到此对象,再交由XMLHttpRequest对象发送到服务端,服务端可以通过普通的request.getParamter方法获取这些参数;
5. progress标签
H5新增的标签,在页面显示一个进度条:
value:当前进度条的值
max:最大值
利用这个标签,结合XMLHttpRequest的回调来反馈目前上传的进度
四、客户端代码示例
HTML代码:
&input type="file" multiple=true onchange="showFileList(this.files)"/&
&input id="uploadBtn" type="button"
value="上传"
onclick="doUpload()"/&&
javascript脚本:
var quence = new Array();
function showFileList(files) {
if(!files) {
var chunkSize = 5 * 1024 * 1024;
$(files).each(function(idx,e){
if(e.size & chunkSize) {
var chunks = Math.max(Math.floor(fileSize / chunkSize), 1)+1;
for(var i=0 ; i& i++) {
var startIdx = i*chunkS
var endIdx = startIdx+chunkS
if(endIdx & fileSize) {
endIdx = fileS
var lastChunk = false;
if(i == (chunks-1)) {
lastChunk = true;
var task = {
uuid:uuid,
chunked:true,
startIdx:startIdx,
endIdx:endIdx,
currChunk:i,
totalChunk:chunks
quence.push(task);
var task = {
uuid:uuid,
chunked:false
quence.push(task);
function Uploader(name) {
this.url="";
this.req = new XMLHttpRequest();
this.taskIdx = 0;
this.name=
this.status=0;
this.upload = function(uploader) {
this.req.responseType = "json";
this.req.addEventListener("load", function(){
progressUpdate(this.response.uuid, this.response.fileSize);
var task = uploader.tasks[uploader.taskIdx];
if(task) {
console.log(uploader.name + ":当前执行的任务编号:" +uploader.taskIdx);
this.open("POST", uploader.url);
this.send(uploader.buildFormData(task));
uploader.taskIdx++;
console.log("处理完毕");
uploader.status=1;
var task = this.tasks[this.taskIdx];
if(task) {
console.log(uploader.name + ":当前执行的任务编号:" +this.taskIdx);
this.req.open("POST", this.url);
this.req.send(this.buildFormData(task));
this.taskIdx++;
uploader.status=1;
this.submit = function(tasks) {
this.tasks =
this.buildFormData = function(task) {
var file = task.
var formData = new FormData();
formData.append("fileName", file.name);
formData.append("fileSize", file.size);
formData.append("uuid", task.uuid);
var chunked = task.
if(chunked) {
formData.append("chunked",
task.chunked);
formData.append("data", file.slice(task.startIdx, task.endIdx));
formData.append("currChunk", task.currChunk);
formData.append("totalChunk", task.totalChunk);
formData.append("data", file);
return formD
function doUpload() {
var uploader0 = new Uploader("uploader0");
var task0 = new Array();
var uploader1 = new Uploader("uploader1");
var task1 = new Array();
var uploader2 = new Uploader("uploader2");
var task2 = new Array();
var uploader3 = new Uploader("uploader3");
var task3 = new Array();
for(var i=0 ; i&quence. i++) {
if(i%4==0) {
task0.push(quence[i]);
} else if(i%4==1) {
task1.push(quence[i]);
} else if(i%4==2) {
task2.push(quence[i]);
} else if(i%4==3) {
task3.push(quence[i]);
/提交任务,启动线程上传
uploader0.submit(task0);
uploader0.upload(uploader0);
uploader1.submit(task1);
uploader1.upload(uploader1);
uploader2.submit(task2);
uploader2.upload(uploader2);
uploader3.submit(task3);
uploader3.upload(uploader3);
uploadCompleteMonitor = setInterval("uploadComplete()",2000);
五、服务端处理:
服务端处理逻辑相对比较传统,利用输入输出流、NIO等把文件写到磁盘即可。
这里需要特别考虑的是关于被切块文件的合并。前端在上传的时候,文件块是无序到达服务端,因此我们在每次接收到一个文件块的时候需要判断被切块的文件是否都传输完毕并进行合并,思路如下:
回到前端,我们在构造被切块的文件formData的数据结构:
formData.append("fileName", file.name)
formData.append("fileSize", file.size)
formData.append("uuid", task.uuid)
formData.append("chunked",
task.chunked)
formData.append("data", file.slice(task.startIdx, task.endIdx))
formData.append("currChunk", task.currChunk)
formData.append("totalChunk", task.totalChunk)
fileName:文件的原始名字
fileSize:文件的大小,KB
uuid:文件的uuid
chunked:true,标识是分段上传的文件块
data:文件二进制流
currChunk:当前上传的块编号
totalChunk:总块数
服务端以文件的UUID为key,维护一个chunk计数器,每接收到一块就找到对应的uuid执行计数器+1,同时考虑到并发情况,需采用同步关键字,避免出现逻辑错误。当计数器等于totalChunk的时候,进行文件合并
六、运行效果
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1871次
排名:千里之外

我要回帖

更多关于 dnf帕拉丁刷图 的文章

 

随机推荐