Skip to content

Commit 8ba04c5

Browse files
committed
1. 允许边hash边上传(配置isUploadAfterHash)
2. 细节优化 Signed-off-by: Devin <[email protected]>
1 parent d39c1ef commit 8ba04c5

10 files changed

+215
-135
lines changed

Q.Uploader.all.js

+65-40
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@
373373
* Q.Uploader.js 文件上传管理器 1.0
374374
* https://github.com/devin87/web-uploader
375375
376-
* update:2016/06/17 13:30
376+
* update:2016/06/30 16:14
377377
*/
378378
(function (window, undefined) {
379379
"use strict";
@@ -531,6 +531,7 @@
531531
chunkSize: 2 * 1024 * 1024, //默认分片大小为2MB
532532
isQueryState:false, //是否查询文件状态(for 秒传或续传)
533533
isMd5: false, //是否计算上传文件md5值
534+
isUploadAfterHash:true, //是否在Hash计算完毕后再上传
534535
535536
container:element, //一般无需指定
536537
getPos:function, //一般无需指定
@@ -599,6 +600,7 @@
599600
self.isSlice = !!ops.isSlice; //是否启用分片上传
600601
self.isQueryState = !!def(ops.isQueryState, self.isSlice); //是否查询文件状态(for 秒传或续传)
601602
self.isMd5 = !!def(ops.isMd5, self.isSlice); //是否计算上传文件md5值
603+
self.isUploadAfterHash = ops.isUploadAfterHash !== false; //是否在Hash计算完毕后再上传
602604

603605
//ie9及以下不支持click触发(即使能弹出文件选择框,也无法获取文件数据,报拒绝访问错误)
604606
//若上传按钮位置不确定(比如在滚动区域内),则无法触发文件选择
@@ -851,7 +853,8 @@
851853
},
852854

853855
//取消上传任务
854-
cancel: function (taskId) {
856+
//onlyCancel: 若为true,则仅取消上传而不触发任务完成事件
857+
cancel: function (taskId, onlyCancel) {
855858
var self = this,
856859
task = self.get(taskId);
857860

@@ -876,7 +879,7 @@
876879
self.iframe.contentWindow.location = "about:blank";
877880
}
878881

879-
return self.complete(task, UPLOAD_STATE_CANCEL);
882+
return onlyCancel ? self : self.complete(task, UPLOAD_STATE_CANCEL);
880883
},
881884

882885
//移除任务
@@ -940,70 +943,92 @@
940943
return self;
941944
},
942945

943-
//处理html5上传
944-
_upload_html5_ready: function (task) {
945-
var self = this;
946-
947-
//查询上传文件的状态(for 秒传或续传)
948-
var query_state = function (callback) {
949-
var url = self.url,
950-
xhr = new XMLHttpRequest();
946+
//根据 task.hash 查询任务状态(for 秒传或续传)
947+
queryState: function (task, callback) {
948+
var self = this,
949+
url = self.url,
950+
xhr = new XMLHttpRequest();
951951

952-
url += (url.indexOf("?") == -1 ? "?" : "&") + "action=query&hash=" + task.hash;
952+
url += (url.indexOf("?") == -1 ? "?" : "&") + "action=query&hash=" + (task.hash || task.name);
953953

954-
xhr.open("GET", url);
955-
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
954+
xhr.open("GET", url);
955+
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
956956

957-
xhr.onreadystatechange = function () {
958-
if (xhr.readyState != 4) return;
957+
xhr.onreadystatechange = function () {
958+
if (xhr.readyState != 4) return;
959959

960-
if (xhr.status >= 200 && xhr.status < 400) {
961-
var result = xhr.responseText;
962-
if (result === "ok") return self.complete(task, UPLOAD_STATE_COMPLETE);
960+
var result;
963961

962+
if (xhr.status >= 200 && xhr.status < 400) {
963+
var result = xhr.responseText;
964+
if (result === "ok") {
965+
self.cancel(task.id, true).complete(task, UPLOAD_STATE_COMPLETE);
966+
} else {
964967
var start = !result || isNaN(result) ? 0 : +result;
965968
if (start != Math.floor(start)) start = 0;
966969

967970
task.sliceStart = start;
968971
}
972+
}
969973

970-
callback();
971-
};
972-
973-
xhr.onerror = function () {
974-
callback();
975-
};
974+
fire(callback, self, xhr, result);
975+
};
976976

977-
xhr.send(null);
977+
xhr.onerror = function () {
978+
fire(callback, self, xhr);
978979
};
979980

981+
xhr.send(null);
982+
983+
return self;
984+
},
985+
986+
//处理html5上传(包括秒传和断点续传)
987+
_upload_html5_ready: function (task) {
988+
var self = this;
989+
980990
//上传处理
981991
var goto_upload = function () {
992+
if (task.state == UPLOAD_STATE_COMPLETE) return;
993+
982994
if (self.isSlice) self._upload_slice(task);
983995
else self._upload_html5(task);
984996
};
985997

986-
var goto_query_state = function () {
998+
var after_hash = function (callback) {
999+
//自定义hash事件
9871000
self.fire("hash", task, function () {
988-
if (task.hash && self.isQueryState) query_state(goto_upload);
989-
else goto_upload();
1001+
if (task.hash && self.isQueryState && task.state != UPLOAD_STATE_COMPLETE) self.queryState(task, callback);
1002+
else callback();
9901003
});
9911004
};
9921005

993-
//计算上传文件md5值
994-
if (self.isMd5 && md5File) {
995-
var hashProgress = self.fns.hashProgress;
1006+
//计算文件hash
1007+
var compute_hash = function (callback) {
1008+
//计算上传文件md5值
1009+
if (self.isMd5 && md5File) {
1010+
var hashProgress = self.fns.hashProgress;
1011+
1012+
md5File(task.file, function (md5, time) {
1013+
task.hash = md5;
1014+
task.timeHash = time;
1015+
after_hash(callback);
1016+
}, function (pvg) {
1017+
fire(hashProgress, self, task, pvg);
1018+
});
1019+
} else {
1020+
after_hash(callback);
1021+
}
1022+
};
9961023

997-
md5File(task.file, function (md5, time) {
998-
task.hash = md5;
999-
task.timeHash = time;
1000-
goto_query_state();
1001-
}, function (pvg) {
1002-
fire(hashProgress, self, task, pvg);
1003-
});
1024+
if (self.isUploadAfterHash) {
1025+
compute_hash(goto_upload);
10041026
} else {
1005-
goto_query_state();
1027+
goto_upload();
1028+
compute_hash();
10061029
}
1030+
1031+
return self;
10071032
},
10081033

10091034
//处理上传参数

Q.Uploader.image.all.js

+65-40
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@
373373
* Q.Uploader.js 文件上传管理器 1.0
374374
* https://github.com/devin87/web-uploader
375375
376-
* update:2016/06/17 13:30
376+
* update:2016/06/30 16:14
377377
*/
378378
(function (window, undefined) {
379379
"use strict";
@@ -531,6 +531,7 @@
531531
chunkSize: 2 * 1024 * 1024, //默认分片大小为2MB
532532
isQueryState:false, //是否查询文件状态(for 秒传或续传)
533533
isMd5: false, //是否计算上传文件md5值
534+
isUploadAfterHash:true, //是否在Hash计算完毕后再上传
534535
535536
container:element, //一般无需指定
536537
getPos:function, //一般无需指定
@@ -599,6 +600,7 @@
599600
self.isSlice = !!ops.isSlice; //是否启用分片上传
600601
self.isQueryState = !!def(ops.isQueryState, self.isSlice); //是否查询文件状态(for 秒传或续传)
601602
self.isMd5 = !!def(ops.isMd5, self.isSlice); //是否计算上传文件md5值
603+
self.isUploadAfterHash = ops.isUploadAfterHash !== false; //是否在Hash计算完毕后再上传
602604

603605
//ie9及以下不支持click触发(即使能弹出文件选择框,也无法获取文件数据,报拒绝访问错误)
604606
//若上传按钮位置不确定(比如在滚动区域内),则无法触发文件选择
@@ -851,7 +853,8 @@
851853
},
852854

853855
//取消上传任务
854-
cancel: function (taskId) {
856+
//onlyCancel: 若为true,则仅取消上传而不触发任务完成事件
857+
cancel: function (taskId, onlyCancel) {
855858
var self = this,
856859
task = self.get(taskId);
857860

@@ -876,7 +879,7 @@
876879
self.iframe.contentWindow.location = "about:blank";
877880
}
878881

879-
return self.complete(task, UPLOAD_STATE_CANCEL);
882+
return onlyCancel ? self : self.complete(task, UPLOAD_STATE_CANCEL);
880883
},
881884

882885
//移除任务
@@ -940,70 +943,92 @@
940943
return self;
941944
},
942945

943-
//处理html5上传
944-
_upload_html5_ready: function (task) {
945-
var self = this;
946-
947-
//查询上传文件的状态(for 秒传或续传)
948-
var query_state = function (callback) {
949-
var url = self.url,
950-
xhr = new XMLHttpRequest();
946+
//根据 task.hash 查询任务状态(for 秒传或续传)
947+
queryState: function (task, callback) {
948+
var self = this,
949+
url = self.url,
950+
xhr = new XMLHttpRequest();
951951

952-
url += (url.indexOf("?") == -1 ? "?" : "&") + "action=query&hash=" + task.hash;
952+
url += (url.indexOf("?") == -1 ? "?" : "&") + "action=query&hash=" + (task.hash || task.name);
953953

954-
xhr.open("GET", url);
955-
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
954+
xhr.open("GET", url);
955+
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
956956

957-
xhr.onreadystatechange = function () {
958-
if (xhr.readyState != 4) return;
957+
xhr.onreadystatechange = function () {
958+
if (xhr.readyState != 4) return;
959959

960-
if (xhr.status >= 200 && xhr.status < 400) {
961-
var result = xhr.responseText;
962-
if (result === "ok") return self.complete(task, UPLOAD_STATE_COMPLETE);
960+
var result;
963961

962+
if (xhr.status >= 200 && xhr.status < 400) {
963+
var result = xhr.responseText;
964+
if (result === "ok") {
965+
self.cancel(task.id, true).complete(task, UPLOAD_STATE_COMPLETE);
966+
} else {
964967
var start = !result || isNaN(result) ? 0 : +result;
965968
if (start != Math.floor(start)) start = 0;
966969

967970
task.sliceStart = start;
968971
}
972+
}
969973

970-
callback();
971-
};
972-
973-
xhr.onerror = function () {
974-
callback();
975-
};
974+
fire(callback, self, xhr, result);
975+
};
976976

977-
xhr.send(null);
977+
xhr.onerror = function () {
978+
fire(callback, self, xhr);
978979
};
979980

981+
xhr.send(null);
982+
983+
return self;
984+
},
985+
986+
//处理html5上传(包括秒传和断点续传)
987+
_upload_html5_ready: function (task) {
988+
var self = this;
989+
980990
//上传处理
981991
var goto_upload = function () {
992+
if (task.state == UPLOAD_STATE_COMPLETE) return;
993+
982994
if (self.isSlice) self._upload_slice(task);
983995
else self._upload_html5(task);
984996
};
985997

986-
var goto_query_state = function () {
998+
var after_hash = function (callback) {
999+
//自定义hash事件
9871000
self.fire("hash", task, function () {
988-
if (task.hash && self.isQueryState) query_state(goto_upload);
989-
else goto_upload();
1001+
if (task.hash && self.isQueryState && task.state != UPLOAD_STATE_COMPLETE) self.queryState(task, callback);
1002+
else callback();
9901003
});
9911004
};
9921005

993-
//计算上传文件md5值
994-
if (self.isMd5 && md5File) {
995-
var hashProgress = self.fns.hashProgress;
1006+
//计算文件hash
1007+
var compute_hash = function (callback) {
1008+
//计算上传文件md5值
1009+
if (self.isMd5 && md5File) {
1010+
var hashProgress = self.fns.hashProgress;
1011+
1012+
md5File(task.file, function (md5, time) {
1013+
task.hash = md5;
1014+
task.timeHash = time;
1015+
after_hash(callback);
1016+
}, function (pvg) {
1017+
fire(hashProgress, self, task, pvg);
1018+
});
1019+
} else {
1020+
after_hash(callback);
1021+
}
1022+
};
9961023

997-
md5File(task.file, function (md5, time) {
998-
task.hash = md5;
999-
task.timeHash = time;
1000-
goto_query_state();
1001-
}, function (pvg) {
1002-
fire(hashProgress, self, task, pvg);
1003-
});
1024+
if (self.isUploadAfterHash) {
1025+
compute_hash(goto_upload);
10041026
} else {
1005-
goto_query_state();
1027+
goto_upload();
1028+
compute_hash();
10061029
}
1030+
1031+
return self;
10071032
},
10081033

10091034
//处理上传参数

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ new Q.Uploader({
116116
//查询路径为: url?action=query&hash=file hash
117117
isQueryState:false, //是否查询文件状态(for 秒传或续传)
118118
isMd5: false, //是否计算上传文件md5值
119+
isUploadAfterHash:true, //是否在Hash计算完毕后再上传
119120
120121
container:element, //一般无需指定
121122
getPos:function, //一般无需指定
@@ -192,7 +193,8 @@ uploader.start();
192193
uploader.upload(task);
193194
194195
//取消上传任务
195-
uploader.cancel(taskId);
196+
//onlyCancel: 若为true,则仅取消上传而不触发任务完成事件
197+
uploader.cancel(taskId, onlyCancel);
196198
197199
//移除上传任务,会先调用 uploader.cancel(taskId)
198200
uploader.remove(taskId);

demo/slice.html

+7-4
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,17 @@
4141
target: document.getElementById("upload-target"),
4242
view: document.getElementById("upload-view"),
4343

44-
isSlice: true,
45-
//chunkSize: 2 * 1024 * 1024,
46-
//isQueryState: true,
44+
isSlice: true, //是否启用分片上传,若为true,则isQueryState和isMd5默认为true
45+
//chunkSize: 2 * 1024 * 1024, //默认分片大小为2MB
46+
//isQueryState: true, //是否查询文件状态(for 秒传或续传)
4747

4848
//基于md5的秒传和断点续传,不限于浏览器或机器,只要文件相同,均可
4949
//若自己实现hash计算,可配置isMd5为false,见下面 hashAsync 事件
5050
//isMd5: true,
5151

52+
//是否在Hash计算完毕后再上传
53+
//isUploadAfterHash: true,
54+
5255
//allows: ".txt,.jpg,.png,.gif,.zip,.rar,.7z",
5356

5457
//每次上传都会发送的参数(POST方式)
@@ -96,7 +99,7 @@
9699
},
97100

98101
//文件hash进度
99-
hashProgress: function (task,pvg) {
102+
hashProgress: function (task, pvg) {
100103
document.title = "hash: " + (pvg * 100).toFixed(2) + "%";
101104
},
102105

0 commit comments

Comments
 (0)