alioss-web-uploader
Version:
Upload file or add object to Ali OSS in browser.
571 lines (555 loc) • 21.9 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.AliOSSWebUploader = factory());
}(this, (function () { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
/**
* remove ^\/+
* @param name
*/
function objectName(name) {
return name.replace(/^\/+/, '');
}
function escapeName(name) {
return encodeURIComponent(name).replace(/%2F/g, '/');
}
function isHttpsProtocol() {
return location && location.protocol === 'https:';
}
// unescape(encodeURIComponent(str))
function utf8Encode(str) {
return unescape(encodeURIComponent(str));
}
/*
export function utf8Decode(str) {
let i, ac, c1, c2, c3, arr = [],
l;
i = ac = c1 = c2 = c3 = 0;
if (str && str.length) {
l = str.length;
str += '';
while (i < l) {
c1 = str.charCodeAt(i);
ac += 1;
if (c1 < 128) {
arr[ac] = String.fromCharCode(c1);
i += 1;
} else if (c1 > 191 && c1 < 224) {
c2 = str.charCodeAt(i + 1);
arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = str.charCodeAt(i + 1);
c3 = str.charCodeAt(i + 2);
arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
}
return arr.join('');
}
*/
/**
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF), msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/**
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num, cnt) {
return (num << cnt) | (num >>> (32 - cnt));
}
/**
* Convert a raw string to a hex string
*/
function rstr2hex(input, hexCase) {
var hex_tab = hexCase ? '0123456789ABCDEF' : '0123456789abcdef', output = '', x, i = 0, l = input.length;
for (; i < l; i += 1) {
x = input.charCodeAt(i);
output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
}
return output;
}
/**
* Convert an array of big-endian words to a string
*/
function binb2rstr(input) {
var i, l = input.length * 32, output = '';
for (i = 0; i < l; i += 8) {
output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF);
}
return output;
}
/**
* Convert a raw string to an array of big-endian words
* Characters >255 have their high-byte silently ignored.
*/
function rstr2binb(input) {
var i, l = input.length * 8, output = Array(input.length >> 2), lo = output.length;
for (i = 0; i < lo; i += 1) {
output[i] = 0;
}
for (i = 0; i < l; i += 8) {
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
}
return output;
}
/**
* Convert a raw string to an arbitrary string encoding
*/
function rstr2any(input, encoding) {
var divisor = encoding.length, remainders = Array(), i, q, x, ld, quotient, dividend, output, full_length;
/* Convert to an array of 16-bit big-endian values, forming the dividend */
dividend = Array(Math.ceil(input.length / 2));
ld = dividend.length;
for (i = 0; i < ld; i += 1) {
dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
}
/**
* Repeatedly perform a long division. The binary array forms the dividend,
* the length of the encoding is the divisor. Once computed, the quotient
* forms the dividend for the next step. We stop when the dividend is zerHashes.
* All remainders are stored for later use.
*/
while (dividend.length > 0) {
quotient = Array();
x = 0;
for (i = 0; i < dividend.length; i += 1) {
x = (x << 16) + dividend[i];
q = Math.floor(x / divisor);
x -= q * divisor;
if (quotient.length > 0 || q > 0) {
quotient[quotient.length] = q;
}
}
remainders[remainders.length] = x;
dividend = quotient;
}
/* Convert the remainders to the output string */
output = '';
for (i = remainders.length - 1; i >= 0; i--) {
output += encoding.charAt(remainders[i]);
}
/* Append leading zero equivalents */
full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
for (i = output.length; i < full_length; i += 1) {
output = encoding[0] + output;
}
return output;
}
/**
* Convert a raw string to a base-64 string
*/
function rstr2b64(input, b64pad) {
if (b64pad === void 0) { b64pad = '='; }
var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var output = '', len = input.length, i, j, triplet;
for (i = 0; i < len; i += 3) {
triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
for (j = 0; j < 4; j += 1) {
if (i * 8 + j * 6 > input.length * 8) {
output += b64pad;
}
else {
output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
}
}
}
return output;
}
/**
* This file is copied from https://github.com/react-component/upload/blob/master/src/request.js
* Thanks the authors.
*/
function getError(url, option, xhr) {
var codePart = xhr.response.match(/<Code>(.+)<\/Code>/);
var messagePart = xhr.response.match(/<Message>(.+)<\/Message>/);
var method = option.method || 'GET';
// let msg = `[${xhr.status}] ${method} ${url}`;
var msg = '';
if (codePart && codePart[1])
msg += codePart[1] + ": ";
if (messagePart && messagePart[1])
msg += messagePart[1];
var err = new Error(msg);
err.status = xhr.status;
err.method = method;
err.code = codePart && codePart[1] || '';
err.url = url;
return err;
}
function getBody(xhr) {
var text = xhr.responseText || xhr.response;
if (!text) {
return text;
}
try {
return JSON.parse(text);
}
catch (e) {
return text;
}
}
function request(url, options) {
var xhr = new XMLHttpRequest();
xhr.timeout = options.timeout || 60000;
if (options.onProgress && xhr.upload) {
xhr.upload.onprogress = function progress(e) {
e.percent = e.loaded / e.total * 100;
options.onProgress(e);
};
}
/*
const formData = new FormData();
if (options.data){
Object.keys(options.data).forEach(key => {
formData.append(key, options.data[key]);
})
}
formData.append(options.filename, options.file);
*/
xhr.onerror = function (e) {
options.onError(e);
};
xhr.onload = function onload() {
if (xhr.status < 200 || xhr.status >= 300) {
return options.onError(getError(url, options, xhr), getBody(xhr));
}
var result = {
status: xhr.status,
statusText: xhr.statusText,
xhr: xhr,
data: getBody(xhr),
};
options.onSuccess(result, xhr);
};
xhr.ontimeout = function timeout(ev) {
var err = new Error("Request timeout, limit " + xhr.timeout + " ms.");
options.onError(err);
};
if (options.onAbort)
xhr.onabort = options.onAbort;
xhr.open(options.method || 'get', url, true);
if (options.withCredentials && 'withCredentials' in xhr) {
xhr.withCredentials = true;
}
var headers = options.headers || {};
if (headers['X-Requested-With'] !== null) {
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
}
for (var h in headers) {
if (headers.hasOwnProperty(h) && headers[h] !== null) {
xhr.setRequestHeader(h, headers[h]);
}
}
// xhr.send(formData);
xhr.send(options.data || null);
return {
abort: function () {
xhr.abort();
},
};
}
/**
* Copy from https://github.com/h2non/jshashes/blob/master/hashes.js
*/
var SHA1 = function SHA1(options) {
/**
* Private config properties. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
* See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
*/
var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
// public methods
this.hex = function (s) {
return rstr2hex(rstr(s, utf8), hexcase);
};
this.b64 = function (s) {
return rstr2b64(rstr(s, utf8), b64pad);
};
this.any = function (s, e) {
return rstr2any(rstr(s, utf8), e);
};
this.raw = function (s) {
return rstr(s, utf8);
};
this.hex_hmac = function (k, d) {
return rstr2hex(rstr_hmac(k, d));
};
this.b64_hmac = function (k, d) {
return rstr2b64(rstr_hmac(k, d), b64pad);
};
this.any_hmac = function (k, d, e) {
return rstr2any(rstr_hmac(k, d), e);
};
/**
* Perform a simple self-test to see if the VM is working
* @return {String} Hexadecimal hash sample
* @public
*/
/*this.vm_test = function () {
return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
};*/
/**
* @description Enable/disable uppercase hexadecimal returned string
* @param {boolean} a
* @return {Object} this
* @public
*/
this.setUpperCase = function (a) {
if (typeof a === 'boolean') {
hexcase = a;
}
return this;
};
/**
* @description Defines a base64 pad string
* @param {string} Pad
* @return {Object} this
* @public
*/
this.setPad = function (Pad) {
b64pad = Pad || b64pad;
return this;
};
/**
* @description Defines a base64 pad string
* @param {boolean} a
* @return {Object} this
* @public
*/
this.setUTF8 = function (a) {
if (typeof a === 'boolean') {
utf8 = a;
}
return this;
};
// private methods
/**
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function binb(x, len) {
var i, j, t, olda, oldb, oldc, oldd, olde, w = Array(80), a = 1732584193, b = -271733879, c = -1732584194, d = 271733878, e = -1009589776;
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
for (i = 0; i < x.length; i += 16) {
olda = a;
oldb = b;
oldc = c;
oldd = d;
olde = e;
for (j = 0; j < 80; j += 1) {
if (j < 16) {
w[j] = x[i + j];
}
else {
w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
}
t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = bit_rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/**
* Calculate the SHA-512 of a raw string
*/
function rstr(s, utf8) {
s = (utf8) ? utf8Encode(s) : s;
return binb2rstr(binb(rstr2binb(s), s.length * 8));
}
/**
* Calculate the HMAC-SHA1 of a key and some data (raw strings)
*/
function rstr_hmac(key, data) {
var bkey, ipad, opad, i, hash;
key = (utf8) ? utf8Encode(key) : key;
data = (utf8) ? utf8Encode(data) : data;
bkey = rstr2binb(key);
if (bkey.length > 16) {
bkey = binb(bkey, key.length * 8);
}
ipad = Array(16), opad = Array(16);
for (i = 0; i < 16; i += 1) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
return binb2rstr(binb(opad.concat(hash), 512 + 160));
}
/**
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d) {
if (t < 20) {
return (b & c) | ((~b) & d);
}
if (t < 40) {
return b ^ c ^ d;
}
if (t < 60) {
return (b & c) | (b & d) | (c & d);
}
return b ^ c ^ d;
}
/**
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t) {
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
};
function computeSignature(accessKeySecret, canonicalString) {
return new SHA1().b64_hmac(accessKeySecret, canonicalString);
}
function getOssParams(params, extendKeys) {
if (extendKeys === void 0) { extendKeys = []; }
var out = {};
Object.keys(params).forEach(function (key) {
var lowerKey = key.toLowerCase();
if (/^x-oss-/.test(lowerKey) || extendKeys.indexOf(key) > -1) {
out[lowerKey] = params[key];
}
});
return out;
}
var Client = /** @class */ (function () {
function Client(options) {
if (!(this instanceof Client)) {
return new Client(options);
}
var opts = __assign(__assign({ endpoint: null, region: 'oss-cn-hangzhou', timeout: 300000, internal: false,
// cname: false,
secure: undefined }, options), { host: '' });
if (opts.endpoint) ;
else if (opts.region && opts.bucket) {
opts.endpoint = opts.bucket;
if (opts.internal)
opts.region += '-internal';
opts.endpoint += "." + opts.region + ".aliyuncs.com";
}
else {
throw new Error('require endpoint or region/bucket in options');
}
// 一般情况下不需要设置 `secure` 参数,唯一需要用到的场景可能就是在 http 页面中使用 https 连接了
opts.host += "http" + (opts.secure === true || isHttpsProtocol() ? 's' : '') + "://" + opts.endpoint;
this.opts = opts;
}
/*
public putObject(name, file: File|BlobPart, options){
}
*/
/**
* post object as form/multi-part
* @param name
* @param file
* @param options
*/
Client.prototype.postObject = function (name, file, options) {
if (options === void 0) { options = {}; }
var policyBase64;
var data = new FormData();
Object.keys(options.headers || {}).forEach(function (key) {
data.append(key, options.headers[key].toString());
});
var objectKey = objectName((options.dir || '').replace(/^(.+?)\/*$/, '$1/') + objectName(name));
data.append('key', objectKey);
if (this.opts.accessKeyId && this.opts.accessKeySecret) {
if (typeof options.policy === 'string') {
policyBase64 = options.policy;
}
else {
var policy = __assign({ "expiration": new Date(+new Date() + 24 * 3600 * 1000).toISOString(), "conditions": [
{ "bucket": this.opts.bucket },
{ "key": objectKey },
["content-length-range", 0, 1024 * 1024 * 1024],
] }, options.policy);
policyBase64 = rstr2b64(utf8Encode(JSON.stringify(policy)));
}
var signature = options.signature || computeSignature(this.opts.accessKeySecret, policyBase64);
data.append('OSSAccessKeyId', this.opts.accessKeyId);
data.append('policy', policyBase64);
data.append('Signature', signature);
if (this.opts.stsToken) {
data.append('x-oss-security-token', this.opts.stsToken);
}
}
var ossParam = getOssParams(options, ['success_action_status', 'success_action_redirect']);
Object.keys(ossParam).forEach(function (k) { return data.append(k, ossParam[k]); });
data.append('file', file);
var emptyFunc = function () { };
var successCallback = options.onSuccess || emptyFunc;
var reqOptions = {
method: 'POST',
data: data,
timeout: options.timeout || this.opts.timeout,
onSuccess: function (result, xhr) { return successCallback(result, xhr); },
onError: options.onError || function (e) {
console.error(e);
},
onAbort: options.onAbort || emptyFunc,
};
if (options.onProgress)
reqOptions.onProgress = options.onProgress;
return request(this.opts.host, reqOptions);
};
/**
* Get the Object url.
* If provide baseUrl, will use baseUrl instead the default bucket and endpoint .
* @param name
* @param baseUrl
*/
Client.prototype.generateObjectUrl = function (name, baseUrl) {
if (!baseUrl) {
baseUrl = this.opts.host + '/';
}
else if (baseUrl[baseUrl.length - 1] !== '/') {
baseUrl += '/';
}
return baseUrl + escapeName(objectName(name));
};
return Client;
}());
return Client;
})));
//# sourceMappingURL=alioss-web-uploader.js.map