html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="file" id="fileUpload"/>
<button id="uploadBtn">上传</button>
<div id="fileNameContent"></div>
<div id="progressContent"></div>
<script type="text/javascript" src="{{ url_for('static',filename='js/jquery.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static',filename='js/fileSliceUpload.js') }}?1"></script>
<script>
var fileSliceObj = new FileSliceUpload({
'fileInputElement':document.getElementById('fileUpload'),
'fileFormats':['zip'],
'uploadBtn' : document.getElementById('uploadBtn'),
'dctId':'7912c86453f8476681ccae34f0ea8c6e',
'fileNameContent' : document.getElementById('fileNameContent'),
'progressContent' : document.getElementById('progressContent')
})
fileSliceObj.init();
</script>
</body>
</html>
javascript:
function FileSliceUpload(opt) {
//文件上传dom元素
this.fileInputElement = opt.fileInputElement;
//文件校验格式数组
this.fileFormats = opt.fileFormats;
//上传按钮
this.uploadBtn = opt.uploadBtn;
//任务id
this.dctId = opt.dctId
//进度div
this.progressContent = opt.progressContent
//文件名称存储区域
this.fileNameContent = opt.fileNameContent
//切割文件大小(字节)10M
this.fileSliceSize = 10*1024*1024
//当前操作file
this.file = null;
}
/**
* 文件上传事件
*/
FileSliceUpload.prototype.init = function () {
var that = this;
this.fileInputElement.onchange = function (event) {
//获取上传文件
that.file = this.files[0];
//校验上传文件
if(that.checkFileType(that)){
//获取上传进度
var formdata = new FormData();
formdata.append('fileName',that.file.name);
formdata.append('dctId',that.dctId);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/get_slice_file_percent',false);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
var responseObj = JSON.parse(xhr.response);
if(responseObj.hasOwnProperty('alreadyFileUploadSize')){
that.progressContent.innerHTML = responseObj['alreadyFileUploadSize']
}
}
};
xhr.send(formdata);
}
}
this.uploadBtn.onclick = function (event) {
if(this.innerHTML == '上传'){
this.innerHTML == '暂停';
//开始上传
var progress = that.progressContent.innerHTML;
var upProgress = 0; //已经上传的字节数
if(progress!=''){
upProgress = parseInt(progress); //续传赋值
}
that.sliceFile(that.file,upProgress,that)
}
}
}
/**
* 文件上传格式校验
*/
FileSliceUpload.prototype.checkFileType = function (that) {
var flag = true;
var errormessage = ''
var separator = that.file.name.lastIndexOf('.');
var extension = that.file.name.substr(separator + 1).toLowerCase();
if(that.fileFormats.indexOf(extension)==-1){
errormessage = '文件格式必须是'+that.fileFormats.join(',');
flag = false;
}
if(errormessage!=''){
$('#errorform h2').html(errormessage);
$('#errorform').modal('show');
setTimeout(function () {
$('#errorform').modal('hide');
}, 1500);
}
return flag;
}
/**
* 文件切割方法
*/
FileSliceUpload.prototype.sliceFile = function (arrayBuffer,currentProgress,that) {
//每10M切割一段,这里只做一个切割演示,实际切割需要循环切割
var len = currentProgress+this.fileSliceSize;
var filelengh = that.fileInputElement.files[0].size;
if(currentProgress == filelengh){
alert('文件上传成功');
return false;
}
var slice = null;
if(len > filelengh){
slice = arrayBuffer.slice(currentProgress, filelengh);
}else{
slice = arrayBuffer.slice(currentProgress, currentProgress+that.fileSliceSize);
}
console.log(slice);
var formdata = new FormData();
formdata.append('file', slice);
//这里是有一个坑的,部分设备无法获取文件名称,和文件类型,这个在最后给出解决方案
formdata.append('filename', that.file.name);
formdata.append('dctId',that.dctId);
formdata.append('currentProgress',currentProgress);
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', function() {
var responseObj = JSON.parse(xhr.response);
that.progressContent.innerHTML = responseObj['alreadyFileUploadSize'];
that.sliceFile(arrayBuffer,parseInt(responseObj['alreadyFileUploadSize']),that);
});
xhr.open('POST', '/upload_slice_file');
xhr.send(formdata);
}
python 后台:
## 获取文件进度
@main.route('/get_slice_file_percent', methods=['GET', 'POST'])
def get_slice_file_percent():
fileName = request.form.get('fileName')
dctId = request.form.get('dctId')
upUrl = os.path.join(os.getcwd(), 'upload_file')
# 文件名称 用上传的文件名md5
filename = hashlib.md5(fileName).hexdigest()[:15] + '.'
extend_one = os.path.splitext(secure_filename(fileName))[1][1:].lower()
extend_two = os.path.splitext(secure_filename(fileName))[0].lower()
# 获取文件扩展名
if extend_one in IMAGES or extend_two in IMAGES:
if extend_one in IMAGES:
filename += extend_one
else:
filename += extend_two
upUrl2 = os.path.join(upUrl, 'images')
elif extend_one in DOCUMENTS or extend_two in DOCUMENTS:
if extend_one in DOCUMENTS:
filename += extend_one
else:
filename += extend_two
upUrl2 = os.path.join(upUrl, 'documents')
elif extend_one in ARCHIVES or extend_two in ARCHIVES:
if extend_one in ARCHIVES:
filename += extend_one
else:
filename += extend_two
upUrl2 = os.path.join(upUrl, 'archives')
elif extend_one in DATA or extend_two in DATA:
if extend_one in DATA:
filename += extend_one
else:
filename += extend_two
upUrl2 = os.path.join(upUrl, 'data')
allupUrl = os.path.join(upUrl2 , dctId, filename)
retData = {}
if os.path.isfile(allupUrl): #继传
alreadyFileUploadSize = os.stat(allupUrl).st_size # 字节为单位
retData['alreadyFileUploadSize'] = alreadyFileUploadSize
retData['filename'] = filename
return gen_json_response(retData)
## 大文件分片上传
@main.route('/upload_slice_file', methods=['GET', 'POST'])
def upload_slice_file():
file = request.files.get("file")
## 生成file
fileName = request.form.get('filename')
dctId = request.form.get('dctId')
currentProgress = long(request.form.get('currentProgress'))
upUrl = os.path.join(os.getcwd(), 'upload_file')
# 文件名称 用上传的文件名md5
filename = hashlib.md5(fileName).hexdigest()[:15] + '.'
extend_one = os.path.splitext(secure_filename(fileName))[1][1:].lower()
extend_two = os.path.splitext(secure_filename(fileName))[0].lower()
# 获取文件扩展名
if extend_one in IMAGES or extend_two in IMAGES:
if extend_one in IMAGES:
filename += extend_one
else:
filename += extend_two
upUrl2 = os.path.join(upUrl , 'images')
elif extend_one in DOCUMENTS or extend_two in DOCUMENTS:
if extend_one in DOCUMENTS:
filename += extend_one
else:
filename += extend_two
upUrl2 = os.path.join(upUrl, 'documents')
elif extend_one in ARCHIVES or extend_two in ARCHIVES:
if extend_one in ARCHIVES:
filename += extend_one
else:
filename += extend_two
upUrl2 = os.path.join(upUrl, 'archives')
elif extend_one in DATA or extend_two in DATA:
if extend_one in DATA:
filename += extend_one
else:
filename += extend_two
upUrl2 = os.path.join(upUrl, 'data')
##upUrl3 = os.path.join(upUrl2, current_user.userId)
##if not os.path.isdir(upUrl3) :
##os.mkdir(upUrl3)
upUrl4 = os.path.join(upUrl2, dctId)
if not os.path.isdir(upUrl4) :
os.mkdir(upUrl4)
upUrl5 = os.path.join(upUrl4, filename)
with open(upUrl5, "ab") as zip:
##zip.seek(currentProgress,0)
zip.write(file.read())
retData = {}
retData['alreadyFileUploadSize'] = os.stat(upUrl5).st_size
retData['filename'] = filename
return gen_json_response(retData)