乐趣区

web uploader 上传大文件总结

由于业务需要,需要上传大文件,已有的版本无法处理 IE 版本,经过调研,百度的 webuploader 支持 IE 浏览器,而且支持计算 MD5 值,进而可以实现秒传的功能。
大文件上传主要分为三部分,预上传,分块上传,合并上传。
预上传:计算 MD5 值,同时获取服务器返回的参数,作为分块上传的参数
分块上传:对文件按照固定的大小进行分块,分块后并上传块,其中参数包含预上传计算的 MD5 值,如果上传的分块已经存在,则跳过执行,如果不存在,则执行分块上传。
合并上传:当所有的分块完成上传后,对文件进行合并上传。
其中,用到 beforeSendFile,afterFileSend 这两个监听函数,其中,监听函数 beforeSendFile,主要是计算 MD5 值,同时进行预上传,用到 defered,是为了等待异步执行的结果。uploadBeforeSend 与 beforeSendFile 对应,uploadBeforeSend 主要有以下功能:
默认的上传参数,可以扩展此对象来控制上传参数。
可以扩展此对象来控制上传头部。
当某个文件的分块在发送前触发,主要用来询问是否要添加附带参数,大文件在开起分片上传的前提下此事件可能会触发多次。afterFileSend 是完成最终的大文件合并上传。
代码如下:

var fileMd5; // 保存文件 MD5 名称
var uploader; // 全局对象 uploader
var dfsId;
var uploadId;
var rnd = GC.gRnd();
var uploadShardSize = parent.gMain.isCeph==”1″?5 * 1024 * 1024:4 * 1024 * 1024;
var discussContent = jQuery(‘#upload_discusscontent’);
if (parent.gMain.diskType == 2) {
discussContent.parent().show();
}
WebUploader.Uploader.register({
“before-send-file” : “beforeSendFile”, // 文件上传之前执行
“before-send” : “beforeSend”, // 文件块上传之前执行
“after-send-file” : “afterSendFile”, // 上传完成之后执行
},
{
// 时间点 1:所有进行上传之前调用此函数
beforeSendFile : function(file) {
console.log(file);
var owner = this.owner
var deferred = WebUploader.Deferred();
// 计算文件的唯一标识,用于断点续传和妙传
(new WebUploader.Uploader()).md5File(file, 0,
10 * 1024 * 1024).progress(
function(percentage) {
jQuery(“#” + file.id).find(“div.state”).text(“ 正在扫描文件 ”) ;
}).then(
function(val) {
fileMd5 = val;
file.fileMd5 = fileMd5
jQuery(“#” + file.id).find(“div.state”).text(“ 成功获取文件信息 ”);
// 放行
var datas = {
// 文件唯一标记
fileMd5 : fileMd5,
diskType: parent.gMain.diskType,
appFileId: ”,
creatorUsn: parent.gMain.groupUsn,
uploadType: file.chunks == 1 ? 1 : 3,
comeFrom: 11,
parentId: (parent.gMain.currentFid == -2) ? -1 : parent.gMain.currentFid,
fileSize: file.size,
groupId: parent.gMain.groupId,
fileName: file.name,
discussContent: (parent.gMain.diskType == 2) ? discussContent.val() : ”,
model: parent.gMain.uploadModel
};
jQuery.ajax({
type : “POST”,
url : parent.gConst.ajaxPostUrl.file + “?func=common:upload&sid=”+parent.gMain.sid +”&rnd=”+rnd,
data: JSON.stringify(datas),
dataType : “json”,
success : function(response) {
console.log(response)
if(response && response.code===’DFS_118′){
owner.skipFile(file);
deferred.reject();
jQuery(“#” + file.id).find(“div.state”).text(“ 秒传 ”);
} else {
// 分块不存在或不完整,重新发送该分块内容
dfsId = response.var.dfsFileId;
uploadId = response.var.uploadId;
deferred.resolve();
}
},
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader(“Content-Type”, “text/javascript; charset=utf-8”);
}
});
});
return deferred.promise();
},
// 每一个分块发送之前执行该操作, 检查当前块是否已经上传
beforeSend : function(block) {
var deferred = WebUploader.Deferred();
dfsId = dfsId;
deferred.resolve();
this.owner.options.formData = {
fileMd5: fileMd5,
start: block.start
};
return deferred.promise();
},
afterSendFile : function(file) {
// 通知合并分块
console.log(file)
var comepleteData = {
diskType: parent.gMain.diskType,
uploadType: file.blocks ? file.blocks.length == 1 ? 1 : 3 : 1,
creatorUsn: parent.gMain.groupUsn,
parentId: (parent.gMain.currentFid == -2) ? -1 : parent.gMain.currentFid,
fileSize: file.size,
groupId: parent.gMain.groupId,
fileName: file.name,
fileMd5: fileMd5,
comeFrom: 11,
uploadId: uploadId,
dfsFileId: dfsId,
model: parent.gMain.uploadModel,
partCount: file.blocks ? file.blocks.length : 1
}
jQuery.ajax({
type : “POST”,
url : parent.gConst.ajaxPostUrl.file+ “?func=common:completeUpload&sid=”+parent.gMain.sid,
data: JSON.stringify(comepleteData),
dataType: ‘json’,
success : function(response) {
var $li = jQuery(‘#’ + file.id);
$li.find(‘p.state’).text(‘ 上传完成 ’);
jQuery(“#ctlBtn”).addClass(‘disabled’);
},
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader(“Content-Type”, “text/javascript; charset=utf-8”);
}
});
}
});
uploader = WebUploader.create({
swf: ‘../resource_drive/js/control/fileupload/Uploader.swf’,
server: ‘service/common/onestfile.do?func=common:onestUpload&sid=’ + parent.gMain.sid,
pick:{
id: ‘#asd’, // 这个 id 是你要点击上传文件按钮的外层 div 的 id
multiple : true // 是否可以批量上传,true 可以同时选择多个文件
},
auto: true,
disableGlobalDnd: true, // 禁用页面拖拽
chunked: true, // 开启分片上传
chunkSize: uploadShardSize, // 分片大小
chunkRetry: 3, // 重传次数
threads: 1, // 同时上传进程
fileSizeLimit: 2000*1024*1024, // 验证文件总大小
fileSingleSizeLimit: 2000*1024*1024, // 验证单个文件大小
resize: false,
});
// 当文件添加进队列
uploader.on(“fileQueued”, function(file) {
// fileList
jQuery(“#divDialogfileupload”).show();
jQuery(“#sexwarning”).css(“display”,”block”);
jQuery(“.upfile_ul”).css(“display”,”block”);
jQuery(“.upfile_ul”).append(“<div id='” + file.id + “‘class=’fileInfo’><img/><span>” + file.name +
“</span><div class=’state’> 等待上传 …</div><span class=’text’><span></div>”);
});
// 文件上传过程中创建进度条
uploader.on(“uploadProgress”, function(file, progress){
var id = jQuery(“#”+file.id);
id.find(“span.text”).text((progress.toFixed(2))*100+”%”)
id.find(“div.state”).text(“ 上传中 …”)
if (progress == 1) {
id.find(“div.state”).text(“ 上传完成 ”)
}
});
// 发送前填充数据
uploader.on(‘uploadBeforeSend’, function( block, data) {
// block 为分块数据。
console.log(block);
console.log(data);
var deferred = WebUploader.Deferred();
// file 为分块对应的 file 对象。
var file = block.file;
var fileMd5 = file.fileMd5;
// 修改 data 可以控制发送哪些携带数据。
// 将存在 file 对象中的 md5 数据携带发送过去。
data.appFileId = “”;//md5
data.fileMd5 = fileMd5;//md5
data.fileName = data.name;
data.diskType = parent.gMain.diskType;
data.uploadType = block.chunks == 1 ? 1 : 3;
data.creatorUsn = parent.gMain.groupUsn;
data.parentId = (parent.gMain.currentFid == -2) ? -1 : parent.gMain.currentFid;
data.fileSize = data.size;
data.groupId = parent.gMain.groupId;
data.model = parent.gMain.uploadModel;
data.fileRealPath = block.file.source.source.webkitRelativePath;
data.comeFrom = 11;
data.dfsFileId = dfsId;
data.blob = data.name;
if (block.chunks !== 1) {
data.uploadId = uploadId;
data.range = block.start + “-” + block.end;
data.partCount = block.chunks;
data.partNum = block.chunk + 1;
}
data.discussContent = (parent.gMain.diskType == 2) ? discussContent.val() : ”;
deferred.resolve();
});
// 上传成功
uploader.on(“uploadSuccess”, function(file) {
var id = jQuery(“#”+file.id);
id.find(“div.state”).text(“ 已上传 ”)
});
// 上传失败
uploader.on(‘uploadError’, function( file) {
var id = jQuery(“#”+file.id);
id.find(“div.state”).text(“ 上传失败 ”)
});
// 上传完成
uploader.on(“uploadComplete”, function(file) {
var id = jQuery(“#”+file.id);
id.find(“div.state”).text(“ 上传完成 ”)
});

退出移动版