Skip to content

Commit a3f2388

Browse files
committed
Support chunk upload in flash runtime
It support ie 9 & 9- to chunk upload through flash mode But there are still some problems waiting to resolve: - the usage of mOxie need to optimize - localStorage polyfill with cookie will cause crash in IE
1 parent cc5c8df commit a3f2388

File tree

5 files changed

+390
-118
lines changed

5 files changed

+390
-118
lines changed

dist/qiniu.js

Lines changed: 194 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/*!
2-
* qiniu-js-sdk v1.0.10-beta
2+
* qiniu-js-sdk v1.0.13-beta
33
*
44
* Copyright 2015 by Qiniu
55
* Released under GPL V2 License.
66
*
77
* GitHub: http://github.com/qiniu/js-sdk
88
*
9-
* Date: 2015-12-9
9+
* Date: 2015-12-10
1010
*/
1111

1212
/*global plupload ,mOxie*/
@@ -16,6 +16,110 @@
1616

1717
;(function( global ){
1818

19+
// var store = function store(key, value) {
20+
// var lsSupport = false,
21+
// data = null;
22+
23+
// // Check for native support
24+
// if (localStorage) {
25+
// lsSupport = true;
26+
// }
27+
28+
// // If value is detected, set new or modify store
29+
// if (typeof value !== "undefined" && value !== null) {
30+
// // Convert object values to JSON
31+
// if ( typeof value === 'object' ) {
32+
// value = JSON.stringify(value);
33+
// }
34+
// // Set the store
35+
// if (lsSupport) { // Native support
36+
// localStorage.setItem(key, value);
37+
// } else { // Use Cookie
38+
// createCookie(key, value, 30);
39+
// }
40+
// }
41+
42+
// // No value supplied, return value
43+
// if (typeof value === "undefined") {
44+
// // Get value
45+
// if (lsSupport) { // Native support
46+
// data = localStorage.getItem(key);
47+
// } else { // Use cookie
48+
// data = readCookie(key);
49+
// }
50+
51+
// // Try to parse JSON...
52+
// try {
53+
// data = JSON.parse(data);
54+
// }
55+
// catch(e) {
56+
// data = data;
57+
// }
58+
59+
// return data;
60+
61+
// }
62+
63+
// // Null specified, remove store
64+
// if (value === null) {
65+
// if (lsSupport) { // Native support
66+
// localStorage.removeItem(key);
67+
// } else { // Use cookie
68+
// createCookie(key, '', -1);
69+
// }
70+
// }
71+
72+
// /**
73+
// * Creates new cookie or removes cookie with negative expiration
74+
// * @param key The key or identifier for the store
75+
// * @param value Contents of the store
76+
// * @param exp Expiration - creation defaults to 30 days
77+
// */
78+
79+
// function createCookie(key, value, exp) {
80+
// var date = new Date();
81+
// date.setTime(date.getTime() + (exp * 24 * 60 * 60 * 1000));
82+
// var expires = "; expires=" + date.toGMTString();
83+
// document.cookie = key + "=" + value + expires + "; path=/";
84+
// }
85+
86+
// /**
87+
// * Returns contents of cookie
88+
// * @param key The key or identifier for the store
89+
// */
90+
91+
// function readCookie(key) {
92+
// var nameEQ = key + "=";
93+
// var ca = document.cookie.split(';');
94+
// for (var i = 0, max = ca.length; i < max; i++) {
95+
// var c = ca[i];
96+
// while (c.charAt(0) === ' ') {
97+
// c = c.substring(1, c.length);
98+
// }
99+
// if (c.indexOf(nameEQ) === 0) {
100+
// return c.substring(nameEQ.length, c.length);
101+
// }
102+
// }
103+
// return null;
104+
// }
105+
106+
// };
107+
108+
if ( !window.localStorage ) {
109+
window.localStorage = {
110+
data: {},
111+
setItem: function (key, value) {
112+
localStorage.data[key] = value;
113+
},
114+
getItem: function (key) {
115+
return localStorage.data[key] || null ;
116+
},
117+
removeItem: function (key) {
118+
localStorage.data[key] = null;
119+
}
120+
};
121+
}
122+
19123
function QiniuJsSDK() {
20124

21125
var that = this;
@@ -402,47 +506,7 @@ function QiniuJsSDK() {
402506
*/
403507
this.uploader = function(op) {
404508

405-
if (op.log_level) {
406-
logger.level = op.log_level;
407-
}
408-
409-
if (!op.domain) {
410-
throw 'domain setting in options is required!';
411-
}
412-
413-
if (!op.browse_button) {
414-
throw 'browse_button setting in options is required!';
415-
}
416-
417-
logger.debug("init uploader start");
418-
419-
logger.debug("environment: ", mOxie.Env);
420-
421-
logger.debug("userAgent: ", navigator.userAgent);
422-
423-
var option = {};
424-
425-
// hold the handler from user passed options
426-
var _Error_Handler = op.init && op.init.Error;
427-
var _FileUploaded_Handler = op.init && op.init.FileUploaded;
428-
429-
// replace the handler for intercept
430-
op.init.Error = function() {};
431-
op.init.FileUploaded = function() {};
432-
433-
that.uptoken_url = op.uptoken_url;
434-
that.token = '';
435-
that.key_handler = typeof op.init.Key === 'function' ? op.init.Key : '';
436-
this.domain = op.domain;
437-
// TODO: ctx is global in scope of a uploader instance
438-
// this maybe cause error
439-
var ctx = '';
440-
var speedCalInfo = {
441-
isResumeUpload: false,
442-
resumeFilesize: 0,
443-
startTime: '',
444-
currentTime: ''
445-
};
509+
/********** inner function define start **********/
446510

447511
// according the different condition to reset chunk size
448512
// and the upload strategy according with the chunk size
@@ -455,7 +519,8 @@ function QiniuJsSDK() {
455519
var isSpecialSafari = (mOxie.Env.browser === "Safari" && mOxie.Env.version <= 5 && mOxie.Env.os === "Windows" && mOxie.Env.osVersion === "7") || (mOxie.Env.browser === "Safari" && mOxie.Env.os === "iOS" && mOxie.Env.osVersion === "7");
456520
// case IE 9-,chunk_size is not empty and flash is included in runtimes
457521
// set op.chunk_size to zero
458-
if (ie && ie <= 9 && op.chunk_size && op.runtimes.indexOf('flash') >= 0) {
522+
//if (ie && ie <= 9 && op.chunk_size && op.runtimes.indexOf('flash') >= 0) {
523+
if (ie && ie <= 9 && op.chunk_size && op.runtimes.indexOf('flash') < 0) {
459524
// link: http://www.plupload.com/docs/Frequently-Asked-Questions#when-to-use-chunking-and-when-not
460525
// when plupload chunk_size setting is't null ,it cause bug in ie8/9 which runs flash runtimes (not support html5) .
461526
op.chunk_size = 0;
@@ -478,10 +543,6 @@ function QiniuJsSDK() {
478543
// if op.chunk_size set 0 will be cause to direct upload
479544
};
480545

481-
reset_chunk_size();
482-
logger.debug("invoke reset_chunk_size()");
483-
logger.debug("op.chunk_size: ", op.chunk_size);
484-
485546
// if op.uptoken has no value
486547
// get token from 'uptoken_url'
487548
// else
@@ -524,6 +585,54 @@ function QiniuJsSDK() {
524585
return key;
525586
};
526587

588+
/********** inner function define end **********/
589+
590+
if (op.log_level) {
591+
logger.level = op.log_level;
592+
}
593+
594+
if (!op.domain) {
595+
throw 'domain setting in options is required!';
596+
}
597+
598+
if (!op.browse_button) {
599+
throw 'browse_button setting in options is required!';
600+
}
601+
602+
logger.debug("init uploader start");
603+
604+
logger.debug("environment: ", mOxie.Env);
605+
606+
logger.debug("userAgent: ", navigator.userAgent);
607+
608+
var option = {};
609+
610+
// hold the handler from user passed options
611+
var _Error_Handler = op.init && op.init.Error;
612+
var _FileUploaded_Handler = op.init && op.init.FileUploaded;
613+
614+
// replace the handler for intercept
615+
op.init.Error = function() {};
616+
op.init.FileUploaded = function() {};
617+
618+
that.uptoken_url = op.uptoken_url;
619+
that.token = '';
620+
that.key_handler = typeof op.init.Key === 'function' ? op.init.Key : '';
621+
this.domain = op.domain;
622+
// TODO: ctx is global in scope of a uploader instance
623+
// this maybe cause error
624+
var ctx = '';
625+
var speedCalInfo = {
626+
isResumeUpload: false,
627+
resumeFilesize: 0,
628+
startTime: '',
629+
currentTime: ''
630+
};
631+
632+
reset_chunk_size();
633+
logger.debug("invoke reset_chunk_size()");
634+
logger.debug("op.chunk_size: ", op.chunk_size);
635+
527636
// compose options with user passed options and default setting
528637
plupload.extend(option, op, {
529638
url: qiniuUploadUrl,
@@ -657,7 +766,7 @@ function QiniuJsSDK() {
657766
if (localFileInfo) {
658767
// TODO: although only the html5 runtime will enter this statement
659768
// but need uniform way to make convertion between string and json
660-
localFileInfo = JSON.parse(localFileInfo);
769+
localFileInfo = that.parseJSON(localFileInfo);
661770
var now = (new Date()).getTime();
662771
var before = localFileInfo.time || 0;
663772
var aDay = 24 * 60 * 60 * 1000; // milliseconds of one day
@@ -713,7 +822,7 @@ function QiniuJsSDK() {
713822
});
714823
}
715824
} else {
716-
logger.debug("directUpload because uploader.runtime !== 'html5' || !chunk_size");
825+
logger.debug("directUpload because uploader.runtime !== 'html5' || uploader.runtime !== 'flash' || !chunk_size");
717826
// direct upload if runtime is not html5
718827
directUpload(up, file, that.key_handler);
719828
}
@@ -740,7 +849,10 @@ function QiniuJsSDK() {
740849
// store the chunk upload info and set next chunk upload url
741850
uploader.bind('ChunkUploaded', function(up, file, info) {
742851
logger.debug("ChunkUploaded event activated");
852+
logger.debug("file: ", file);
853+
logger.debug("info: ", info);
743854
var res = that.parseJSON(info.response);
855+
logger.debug("res: ", res);
744856
// ctx should look like '[chunk01_ctx],[chunk02_ctx],[chunk03_ctx],...'
745857
ctx = ctx ? ctx + ',' + res.ctx : res.ctx;
746858
var leftSize = info.total - info.offset;
@@ -750,8 +862,9 @@ function QiniuJsSDK() {
750862
up.setOption({
751863
'url': qiniuUploadUrl + '/mkblk/' + leftSize
752864
});
865+
logger.debug("up.setOption url: ", qiniuUploadUrl + '/mkblk/' + leftSize);
753866
}
754-
localStorage.setItem(file.name, JSON.stringify({
867+
localStorage.setItem(file.name, that.stringifyJSON({
755868
ctx: ctx,
756869
percent: file.percent,
757870
total: info.total,
@@ -862,7 +975,8 @@ function QiniuJsSDK() {
862975
uploader.bind('FileUploaded', (function(_FileUploaded_Handler) {
863976
return function(up, file, info) {
864977
logger.debug("FileUploaded event activated");
865-
978+
logger.debug("file: ", file);
979+
logger.debug("info: ", info);
866980
var last_step = function(up, file, info) {
867981
if (op.downtoken_url) {
868982
// if op.dowontoken_url is not empty
@@ -882,7 +996,7 @@ function QiniuJsSDK() {
882996
var info_extended = {};
883997
plupload.extend(info_extended, that.parseJSON(info), res_downtoken);
884998
if (_FileUploaded_Handler) {
885-
_FileUploaded_Handler(up, file, JSON.stringify(info_extended));
999+
_FileUploaded_Handler(up, file, that.stringifyJSON(info_extended));
8861000
}
8871001
} else {
8881002
uploader.trigger('Error', {
@@ -908,15 +1022,18 @@ function QiniuJsSDK() {
9081022
// we need request the mkfile to compose all uploaded chunks
9091023
// else
9101024
// invalke the last_step
1025+
logger.debug("ctx: ", ctx);
9111026
if (ctx) {
9121027
var key = '';
1028+
logger.debug("save_key: ", op.save_key);
9131029
if (!op.save_key) {
9141030
key = getFileKey(up, file, that.key_handler);
9151031
key = key ? '/key/' + that.URLSafeBase64Encode(key) : '';
9161032
}
9171033

9181034
var fname = '/fname/' + that.URLSafeBase64Encode(file.name);
9191035

1036+
logger.debug("op.x_vars: ", op.x_vars);
9201037
var x_vars = op.x_vars,
9211038
x_val = '',
9221039
x_vars_url = '';
@@ -934,27 +1051,46 @@ function QiniuJsSDK() {
9341051
}
9351052

9361053
var url = qiniuUploadUrl + '/mkfile/' + file.size + key + fname + x_vars_url;
937-
var ajax = that.createAjax();
1054+
1055+
var ie = that.detectIEVersion();
1056+
var ajax;
1057+
if (ie && ie <= 9) {
1058+
ajax = new mOxie.XMLHttpRequest();
1059+
mOxie.Env.swf_url = op.flash_swf_url;
1060+
}else{
1061+
ajax = that.createAjax();
1062+
}
9381063
ajax.open('POST', url, true);
9391064
ajax.setRequestHeader('Content-Type', 'text/plain;charset=UTF-8');
9401065
ajax.setRequestHeader('Authorization', 'UpToken ' + that.token);
941-
ajax.onreadystatechange = function() {
1066+
var onreadystatechange = function(){
1067+
logger.debug("ajax.readyState: ", ajax.readyState);
9421068
if (ajax.readyState === 4) {
9431069
localStorage.removeItem(file.name);
1070+
var info;
9441071
if (ajax.status === 200) {
945-
var info = ajax.responseText;
1072+
info = ajax.responseText;
1073+
logger.debug("mkfile is success: ", info);
9461074
last_step(up, file, info);
9471075
} else {
948-
uploader.trigger('Error', {
1076+
info = {
9491077
status: ajax.status,
9501078
response: ajax.responseText,
9511079
file: file,
9521080
code: -200
953-
});
1081+
};
1082+
logger.debug("mkfile is error: ", info);
1083+
uploader.trigger('Error', info);
9541084
}
9551085
}
9561086
};
1087+
if (ie && ie <= 9) {
1088+
ajax.bind('readystatechange', onreadystatechange);
1089+
}else{
1090+
ajax.onreadystatechange = onreadystatechange;
1091+
}
9571092
ajax.send(ctx);
1093+
logger.debug("mkfile: ", url);
9581094
} else {
9591095
last_step(up, file, info.response);
9601096
}

0 commit comments

Comments
 (0)