You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

267 lines
6.7 KiB

(function(win) {
function forEach(m, callback) {
for (var key in m) {
callback(key, m[key]);
}
}
function buildUrl(url, items) {
var query = '';
forEach(items, function(name, value) {
if (name != 'token') {
query += (query ? '&' : '') + encodeURIComponent(name) + '=' + encodeURIComponent(value);
}
});
if (query) {
url += (url.indexOf('?') > 0 ? '&' : '?') + query;
}
return url;
}
function encode2UTF8(argString) {
if (argString === null || typeof argString === 'undefined') {
return '';
}
var string = (argString + ''); // .replace(/\r\n/g, '\n').replace(/\r/g, '\n');
var utftext = '',
start, end, stringl = 0;
start = end = 0;
stringl = string.length;
for (var n = 0; n < stringl; n++) {
var c1 = string.charCodeAt(n);
var enc = null;
if (c1 < 128) {
end++;
} else if (c1 > 127 && c1 < 2048) {
enc = String.fromCharCode(
(c1 >> 6) | 192, (c1 & 63) | 128
);
} else if (c1 & 0xF800 ^ 0xD800 > 0) {
enc = String.fromCharCode(
(c1 >> 12) | 224, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128
);
} else { // surrogate pairs
if (c1 & 0xFC00 ^ 0xD800 > 0) {
throw new RangeError('Unmatched trail surrogate at ' + n);
}
var c2 = string.charCodeAt(++n);
if (c2 & 0xFC00 ^ 0xDC00 > 0) {
throw new RangeError('Unmatched lead surrogate at ' + (n - 1));
}
c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000;
enc = String.fromCharCode(
(c1 >> 18) | 240, ((c1 >> 12) & 63) | 128, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128
);
}
if (enc !== null) {
if (end > start) {
utftext += string.slice(start, end);
}
utftext += enc;
start = end = n + 1;
}
}
if (end > start) {
utftext += string.slice(start, stringl);
}
return utftext;
}
// Copy 七牛 SDK 方法
function encode2Base64(data) {
var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
ac = 0,
enc = '',
tmp_arr = [];
if (!data) {
return data;
}
data = encode2UTF8(data + '');
do { // pack three octets into four hexets
o1 = data.charCodeAt(i++);
o2 = data.charCodeAt(i++);
o3 = data.charCodeAt(i++);
bits = o1 << 16 | o2 << 8 | o3;
h1 = bits >> 18 & 0x3f;
h2 = bits >> 12 & 0x3f;
h3 = bits >> 6 & 0x3f;
h4 = bits & 0x3f;
// use hexets to index into b64, and append result to encoded string
tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
} while (i < data.length);
enc = tmp_arr.join('');
switch (data.length % 3) {
case 1:
enc = enc.slice(0, -2) + '==';
break;
case 2:
enc = enc.slice(0, -1) + '=';
break;
}
return enc;
}
// Copy 七牛 SDK 方法
function URLSafeBase64Encode(v) {
v = encode2Base64(v);
return v.replace(/\//g, '_').replace(/\+/g, '-');
}
function chunkLastStep(data, opts, callback) {
// 七牛 URL 规定
var key = '/key/' + URLSafeBase64Encode(data.filename);
var fname = '/fname/' + URLSafeBase64Encode(data.filename);
var url = opts.domain + '/mkfile/' + data.size + key + fname;
var options = {
domain: url,
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream'
},
multi_parmas: opts.multi_parmas,
support_options: true,
stream: true
};
uploadData(data.ctx, options, {
onCompleted: function(res) {
res.filename = data.filename;
res.name = data.name;
callback.onCompleted(res);
},
onError: function() {
throw new Error('qiniu uploadChunk error');
},
onProgress: function(chunkLoaded, total) {},
onOpen: function(xhr) {
callback.onOpen(xhr);
}
});
}
var offset = 0,
ctxStore = {};
function uploadNextChunk(blob, opts, callback) {
var chunk = Math.ceil(offset / opts.chunk_size),
chunks = Math.ceil(blob.size / opts.chunk_size),
curChunkSize = Math.min(opts.chunk_size, blob.size - offset),
chunkBlob = blob.slice(offset, offset + curChunkSize),
chunkInfo = {
chunk: chunk,
chunks: chunks,
name: blob.uniqueName
};
forEach(chunkInfo, function(key, value) {
opts.multi_parmas[key] = value;
});
opts.filesize = blob.size;
opts.headers = {
'Content-Type': 'application/octet-stream'
};
opts.isChunk = true;
uploadData(chunkBlob, opts, {
onCompleted: function(chunkRes) {
offset += curChunkSize;
// callback.onProgress(Math.floor((chunk + 1) / chunks * blob.size), blob.size);
ctxStore[blob.uniqueName] = ctxStore[blob.uniqueName] || [];
ctxStore[blob.uniqueName].push(chunkRes.ctx);
if (offset < blob.size) {
if (chunkRes.ctx) {
uploadNextChunk(blob, opts, callback);
}else{
offset = 0;
delete ctxStore[blob.uniqueName]
}
} else {
offset = 0;
delete opts.isChunk;
delete opts.headers['Content-Type'];
forEach(chunkInfo, function(key, value) {
delete opts.multi_parmas[key];
});
var ctx = ctxStore[blob.uniqueName].join(',');
var data = {
ctx: ctx,
name: blob.name,
size: blob.size,
filename: blob.uniqueName
};
chunkLastStep(data, opts, callback);
}
},
onError: function() {
throw new Error('qiniu uploadChunk error');
},
onProgress: function(chunkLoaded, total) {
var loaded = chunkLoaded + offset;
callback.onProgress(loaded, opts.filesize);
},
onOpen: function(xhr) {
callback.onOpen(xhr);
}
});
}
function uploadData(data, options, callback) {
var xhr = new XMLHttpRequest();
if (xhr.upload && options.support_options) {
xhr.upload.onprogress = function(event) {
callback.onProgress(event.loaded, event.total);
};
}
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
var result = xhr.responseText || "{}";
result = JSON.parse(result);
result.filename = options.unique_value;
callback.onCompleted(result);
}
};
var url = options.domain;
if (options.isChunk) {
url += '/mkblk/' + data.size;
url = buildUrl(url, options.multi_parmas);
}
xhr.open(options.method, url, true);
callback.onOpen(xhr);
if (options.stream) {
xhr.setRequestHeader('authorization', 'UpToken ' + options.multi_parmas.token);
}
forEach(options.headers, function(key, value) {
xhr.setRequestHeader(key, value);
});
xhr.send(data);
}
function uploadQiniu(file, opts, callback) {
if (file.size && opts.chunk_size < file.size) {
var uniqueName = opts['genUId'](file);
var suffix = file.name.substr(file.name.lastIndexOf('.'));
uniqueName = uniqueName + suffix;
file.uniqueName = uniqueName;
opts.stream = true;
uploadNextChunk(file, opts, callback);
} else {
var data = opts['data'](file, opts);
uploadData(data, opts, callback);
}
}
win.uploadProcess = uploadQiniu;
})(window);