<script>
var $form = null;
$(function () {
$form = $('#fileupload').fileupload({
dataType: 'json',
/*xhrFields: {withCredentials: true},*/
complete: function (e, data) {
//code for done uploading callback
console.log(e.responseJSON);
}
});
});
$('#fileupload').addClass('fileupload-processing');
</script>
<form id="fileupload" method="POST" enctype="multipart/form-data" data-url="http://remote.com/FileUpload/Upload">
</form>
//data-url 修改为要提交的跨域网站上传服务地址
如果不采用分块上传,经常会遇到上传大文件失败的情况,比如IIS默认传输文件大小为30M,最大允许传输为2G。 就算启用IIS的最大值,过大的文件传输也是容易失败的。
分块上传总体来说还是比较繁琐,需要前后端一起配合,前端代码需要对文件进行切片、计算,后端代码还需要按照传输的文件,按照次序进行组装。
<script>
var $form = null;
var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
var collection = {};
$(function() {
$('#fileupload').fileupload({
dataType: 'json',
maxChunkSize: 10000000,
//分块上传
// 上传完成后的执行逻辑
done: function(e, data) {
$.each(data.result.files,
function(index, file) {
$('<p/>').text(file.name).appendTo(document.body);
});
},
complete: function(e, data) {
//code for done uploading callback
console.log(e.responseJSON);
},
beforeSend: function(xhr, data) {
data.files.forEach(function(file) {
xhr.setRequestHeader('X-File-Identifier', collection[file.name + file.size]);
}
);
},
// 上传过程中的回调函数
progressall: function(e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$(".bar").text(progress + '%');
$('#progress .bar').css('width', progress + '%');
}
}).bind('fileuploadadd',
function(e, data) {
//console.log("add");
data.files.forEach(function(file) {
spark = new SparkMD5.ArrayBuffer();
chunkSize = 10000000; // read in chunks of 10MB
fileid = "";
frOnload = function(e) {
spark.append(e.target.result); // append array buffer
fileid = spark.end();
//保存文件 hash代码
collection[file.name + file.size] = fileid;
}
function loadFile() {
var fileReader = new FileReader();
fileReader.onload = frOnload;
var start = 0,
end = ((start + chunkSize) >= file.size) ? file.size: start + chunkSize;
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
};
loadFile();
}
);
});
});</script>
在配置jQuery File Upload 的时候只要配置参数maxChunkSize就可以切换到分块上传模式,由于后台只有一个上传接口,所以需要在一些特殊文件头来区分出是否分块上传。
其实jQuery File Upload 本身就包含新加的头
分块第一个
Content-Range:bytes 0-9999999/167780896
分块第二个
Content-Range:bytes 10000000-19999999/167780896
最有一个
bytes 160000000-167780895/167780896
可以根据上面的HTTP头信息获得分块的次序
后来我又在之前基础上配置了一个HTTP头X-File-Identifier
,主要考虑用这个标识来唯一确认文件,也可以称之为文件的ID。在用户选择需要上传的文件时,也就是绑定在 add 事件上,采用SparkMD5计算文件的md5码。下面的方法就是对所有新选择的文件进行 md5编码计算。考虑到有的文件过大,比如4G大小的文件,计算md5编码就好久,所以最多也就读取10MB
data.files.forEach(function(file) {
spark = new SparkMD5.ArrayBuffer();
chunkSize = 10000000; // read 10MB
fileid = "";
frOnload = function(e) {
spark.append(e.target.result); // append array buffer
fileid = spark.end();
collection[file.name + file.size] = fileid;
}
function loadFile() {
var fileReader = new FileReader();
fileReader.onload = frOnload;
var start = 0,
end = ((start + chunkSize) >= file.size) ? file.size: start + chunkSize;
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
};
loadFile();
});
为了方便上传后端后,能够识别文件的 唯一编码 (hash编码),需要在上传前在HTTP头信息中加入文件标识
data.files.forEach(function(file) {
xhr.setRequestHeader('X-File-Identifier', collection[file.name + file.size]);
}
其实我觉得在这里还能添加一些验证的头信息,比如JWT登录票据,这样也能有效的保证只有登录用户才能上传文件。