helper.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
  3. var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
  4. _Object$defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.getChunks = getChunks;
  8. exports.isMetaDataValid = isMetaDataValid;
  9. exports.isCustomVarsValid = isCustomVarsValid;
  10. exports.sum = sum;
  11. exports.setLocalFileInfo = setLocalFileInfo;
  12. exports.createLocalKey = createLocalKey;
  13. exports.removeLocalFileInfo = removeLocalFileInfo;
  14. exports.getLocalFileInfo = getLocalFileInfo;
  15. exports.getAuthHeaders = getAuthHeaders;
  16. exports.getHeadersForChunkUpload = getHeadersForChunkUpload;
  17. exports.getHeadersForMkFile = getHeadersForMkFile;
  18. exports.createXHR = createXHR;
  19. exports.computeMd5 = computeMd5;
  20. exports.readAsArrayBuffer = readAsArrayBuffer;
  21. exports.request = request;
  22. exports.getPortFromUrl = getPortFromUrl;
  23. exports.getDomainFromUrl = getDomainFromUrl;
  24. exports.getPutPolicy = getPutPolicy;
  25. exports.createObjectURL = createObjectURL;
  26. exports.MB = void 0;
  27. var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
  28. var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
  29. var _iterator = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/symbol/iterator"));
  30. var _symbol = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/symbol"));
  31. var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
  32. var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));
  33. var _sparkMd = _interopRequireDefault(require("spark-md5"));
  34. var _errors = require("../errors");
  35. var _base = require("./base64");
  36. var __assign = void 0 && (void 0).__assign || function () {
  37. __assign = _assign["default"] || function (t) {
  38. for (var s, i = 1, n = arguments.length; i < n; i++) {
  39. s = arguments[i];
  40. for (var p in s) {
  41. if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
  42. }
  43. }
  44. return t;
  45. };
  46. return __assign.apply(this, arguments);
  47. };
  48. var __awaiter = void 0 && (void 0).__awaiter || function (thisArg, _arguments, P, generator) {
  49. function adopt(value) {
  50. return value instanceof P ? value : new P(function (resolve) {
  51. resolve(value);
  52. });
  53. }
  54. return new (P || (P = _promise["default"]))(function (resolve, reject) {
  55. function fulfilled(value) {
  56. try {
  57. step(generator.next(value));
  58. } catch (e) {
  59. reject(e);
  60. }
  61. }
  62. function rejected(value) {
  63. try {
  64. step(generator["throw"](value));
  65. } catch (e) {
  66. reject(e);
  67. }
  68. }
  69. function step(result) {
  70. result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
  71. }
  72. step((generator = generator.apply(thisArg, _arguments || [])).next());
  73. });
  74. };
  75. var __generator = void 0 && (void 0).__generator || function (thisArg, body) {
  76. var _ = {
  77. label: 0,
  78. sent: function sent() {
  79. if (t[0] & 1) throw t[1];
  80. return t[1];
  81. },
  82. trys: [],
  83. ops: []
  84. },
  85. f,
  86. y,
  87. t,
  88. g;
  89. return g = {
  90. next: verb(0),
  91. "throw": verb(1),
  92. "return": verb(2)
  93. }, typeof _symbol["default"] === "function" && (g[_iterator["default"]] = function () {
  94. return this;
  95. }), g;
  96. function verb(n) {
  97. return function (v) {
  98. return step([n, v]);
  99. };
  100. }
  101. function step(op) {
  102. if (f) throw new TypeError("Generator is already executing.");
  103. while (_) {
  104. try {
  105. if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
  106. if (y = 0, t) op = [op[0] & 2, t.value];
  107. switch (op[0]) {
  108. case 0:
  109. case 1:
  110. t = op;
  111. break;
  112. case 4:
  113. _.label++;
  114. return {
  115. value: op[1],
  116. done: false
  117. };
  118. case 5:
  119. _.label++;
  120. y = op[1];
  121. op = [0];
  122. continue;
  123. case 7:
  124. op = _.ops.pop();
  125. _.trys.pop();
  126. continue;
  127. default:
  128. if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
  129. _ = 0;
  130. continue;
  131. }
  132. if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
  133. _.label = op[1];
  134. break;
  135. }
  136. if (op[0] === 6 && _.label < t[1]) {
  137. _.label = t[1];
  138. t = op;
  139. break;
  140. }
  141. if (t && _.label < t[2]) {
  142. _.label = t[2];
  143. _.ops.push(op);
  144. break;
  145. }
  146. if (t[2]) _.ops.pop();
  147. _.trys.pop();
  148. continue;
  149. }
  150. op = body.call(thisArg, _);
  151. } catch (e) {
  152. op = [6, e];
  153. y = 0;
  154. } finally {
  155. f = t = 0;
  156. }
  157. }
  158. if (op[0] & 5) throw op[1];
  159. return {
  160. value: op[0] ? op[1] : void 0,
  161. done: true
  162. };
  163. }
  164. };
  165. var MB = Math.pow(1024, 2); // 文件分块
  166. exports.MB = MB;
  167. function getChunks(file, blockSize) {
  168. var chunkByteSize = blockSize * MB; // 转换为字节
  169. // 如果 chunkByteSize 比文件大,则直接取文件的大小
  170. if (chunkByteSize > file.size) {
  171. chunkByteSize = file.size;
  172. } else {
  173. // 因为最多 10000 chunk,所以如果 chunkSize 不符合则把每片 chunk 大小扩大两倍
  174. while (file.size > chunkByteSize * 10000) {
  175. chunkByteSize *= 2;
  176. }
  177. }
  178. var chunks = [];
  179. var count = Math.ceil(file.size / chunkByteSize);
  180. for (var i = 0; i < count; i++) {
  181. var chunk = file.slice(chunkByteSize * i, i === count - 1 ? file.size : chunkByteSize * (i + 1));
  182. chunks.push(chunk);
  183. }
  184. return chunks;
  185. }
  186. function isMetaDataValid(params) {
  187. return (0, _keys["default"])(params).every(function (key) {
  188. return key.indexOf('x-qn-meta-') === 0;
  189. });
  190. }
  191. function isCustomVarsValid(params) {
  192. return (0, _keys["default"])(params).every(function (key) {
  193. return key.indexOf('x:') === 0;
  194. });
  195. }
  196. function sum(list) {
  197. return list.reduce(function (data, loaded) {
  198. return data + loaded;
  199. }, 0);
  200. }
  201. function setLocalFileInfo(localKey, info, logger) {
  202. try {
  203. localStorage.setItem(localKey, (0, _stringify["default"])(info));
  204. } catch (err) {
  205. logger.warn(new _errors.QiniuError(_errors.QiniuErrorName.WriteCacheFailed, "setLocalFileInfo failed: " + localKey));
  206. }
  207. }
  208. function createLocalKey(name, key, size) {
  209. var localKey = key == null ? '_' : "_key_" + key + "_";
  210. return "qiniu_js_sdk_upload_file_name_" + name + localKey + "size_" + size;
  211. }
  212. function removeLocalFileInfo(localKey, logger) {
  213. try {
  214. localStorage.removeItem(localKey);
  215. } catch (err) {
  216. logger.warn(new _errors.QiniuError(_errors.QiniuErrorName.RemoveCacheFailed, "removeLocalFileInfo failed. key: " + localKey));
  217. }
  218. }
  219. function getLocalFileInfo(localKey, logger) {
  220. var localInfoString = null;
  221. try {
  222. localInfoString = localStorage.getItem(localKey);
  223. } catch (_a) {
  224. logger.warn(new _errors.QiniuError(_errors.QiniuErrorName.ReadCacheFailed, "getLocalFileInfo failed. key: " + localKey));
  225. }
  226. if (localInfoString == null) {
  227. return null;
  228. }
  229. var localInfo = null;
  230. try {
  231. localInfo = JSON.parse(localInfoString);
  232. } catch (_b) {
  233. // 本地信息已被破坏,直接删除
  234. removeLocalFileInfo(localKey, logger);
  235. logger.warn(new _errors.QiniuError(_errors.QiniuErrorName.InvalidCacheData, "getLocalFileInfo failed to parse. key: " + localKey));
  236. }
  237. return localInfo;
  238. }
  239. function getAuthHeaders(token) {
  240. var auth = 'UpToken ' + token;
  241. return {
  242. Authorization: auth
  243. };
  244. }
  245. function getHeadersForChunkUpload(token) {
  246. var header = getAuthHeaders(token);
  247. return __assign({
  248. 'content-type': 'application/octet-stream'
  249. }, header);
  250. }
  251. function getHeadersForMkFile(token) {
  252. var header = getAuthHeaders(token);
  253. return __assign({
  254. 'content-type': 'application/json'
  255. }, header);
  256. }
  257. function createXHR() {
  258. if (window.XMLHttpRequest) {
  259. return new XMLHttpRequest();
  260. }
  261. if (window.ActiveXObject) {
  262. return new window.ActiveXObject('Microsoft.XMLHTTP');
  263. }
  264. throw new _errors.QiniuError(_errors.QiniuErrorName.NotAvailableXMLHttpRequest, 'the current environment does not support.');
  265. }
  266. function computeMd5(data) {
  267. return __awaiter(this, void 0, void 0, function () {
  268. var buffer, spark;
  269. return __generator(this, function (_a) {
  270. switch (_a.label) {
  271. case 0:
  272. return [4
  273. /*yield*/
  274. , readAsArrayBuffer(data)];
  275. case 1:
  276. buffer = _a.sent();
  277. spark = new _sparkMd["default"].ArrayBuffer();
  278. spark.append(buffer);
  279. return [2
  280. /*return*/
  281. , spark.end()];
  282. }
  283. });
  284. });
  285. }
  286. function readAsArrayBuffer(data) {
  287. return new _promise["default"](function (resolve, reject) {
  288. var reader = new FileReader(); // evt 类型目前存在问题 https://github.com/Microsoft/TypeScript/issues/4163
  289. reader.onload = function (evt) {
  290. if (evt.target) {
  291. var body = evt.target.result;
  292. resolve(body);
  293. } else {
  294. reject(new _errors.QiniuError(_errors.QiniuErrorName.InvalidProgressEventTarget, 'progress event target is undefined'));
  295. }
  296. };
  297. reader.onerror = function () {
  298. reject(new _errors.QiniuError(_errors.QiniuErrorName.FileReaderReadFailed, 'fileReader read failed'));
  299. };
  300. reader.readAsArrayBuffer(data);
  301. });
  302. }
  303. function request(url, options) {
  304. return new _promise["default"](function (resolve, reject) {
  305. var xhr = createXHR();
  306. xhr.open(options.method, url);
  307. if (options.onCreate) {
  308. options.onCreate(xhr);
  309. }
  310. if (options.headers) {
  311. var headers_1 = options.headers;
  312. (0, _keys["default"])(headers_1).forEach(function (k) {
  313. xhr.setRequestHeader(k, headers_1[k]);
  314. });
  315. }
  316. xhr.upload.addEventListener('progress', function (evt) {
  317. if (evt.lengthComputable && options.onProgress) {
  318. options.onProgress({
  319. loaded: evt.loaded,
  320. total: evt.total
  321. });
  322. }
  323. });
  324. xhr.onreadystatechange = function () {
  325. var responseText = xhr.responseText;
  326. if (xhr.readyState !== 4) {
  327. return;
  328. }
  329. var reqId = xhr.getResponseHeader('x-reqId') || '';
  330. if (xhr.status === 0) {
  331. // 发生 0 基本都是网络错误,常见的比如跨域、断网、host 解析失败、系统拦截等等
  332. reject(new _errors.QiniuNetworkError('network error.', reqId));
  333. return;
  334. }
  335. if (xhr.status !== 200) {
  336. var message = "xhr request failed, code: " + xhr.status;
  337. if (responseText) {
  338. message += " response: " + responseText;
  339. }
  340. var data = void 0;
  341. try {
  342. data = JSON.parse(responseText);
  343. } catch (_a) {// 无需处理该错误、可能拿到非 json 格式的响应是预期的
  344. }
  345. reject(new _errors.QiniuRequestError(xhr.status, reqId, message, data));
  346. return;
  347. }
  348. try {
  349. resolve({
  350. data: JSON.parse(responseText),
  351. reqId: reqId
  352. });
  353. } catch (err) {
  354. reject(err);
  355. }
  356. };
  357. xhr.send(options.body);
  358. });
  359. }
  360. function getPortFromUrl(url) {
  361. if (url && url.match) {
  362. var groups = url.match(/(^https?)/);
  363. if (!groups) {
  364. return '';
  365. }
  366. var type = groups[1];
  367. groups = url.match(/^https?:\/\/([^:^/]*):(\d*)/);
  368. if (groups) {
  369. return groups[2];
  370. }
  371. if (type === 'http') {
  372. return '80';
  373. }
  374. return '443';
  375. }
  376. return '';
  377. }
  378. function getDomainFromUrl(url) {
  379. if (url && url.match) {
  380. var groups = url.match(/^https?:\/\/([^:^/]*)/);
  381. return groups ? groups[1] : '';
  382. }
  383. return '';
  384. }
  385. function getPutPolicy(token) {
  386. if (!token) throw new _errors.QiniuError(_errors.QiniuErrorName.InvalidToken, 'invalid token.');
  387. var segments = token.split(':');
  388. if (segments.length === 1) throw new _errors.QiniuError(_errors.QiniuErrorName.InvalidToken, 'invalid token segments.'); // token 构造的差异参考:https://github.com/qbox/product/blob/master/kodo/auths/UpToken.md#admin-uptoken-authorization
  389. var assessKey = segments.length > 3 ? segments[1] : segments[0];
  390. if (!assessKey) throw new _errors.QiniuError(_errors.QiniuErrorName.InvalidToken, 'missing assess key field.');
  391. var putPolicy = null;
  392. try {
  393. putPolicy = JSON.parse((0, _base.urlSafeBase64Decode)(segments[segments.length - 1]));
  394. } catch (error) {
  395. throw new _errors.QiniuError(_errors.QiniuErrorName.InvalidToken, 'token parse failed.');
  396. }
  397. if (putPolicy == null) {
  398. throw new _errors.QiniuError(_errors.QiniuErrorName.InvalidToken, 'putPolicy is null.');
  399. }
  400. if (putPolicy.scope == null) {
  401. throw new _errors.QiniuError(_errors.QiniuErrorName.InvalidToken, 'scope field is null.');
  402. }
  403. var bucketName = putPolicy.scope.split(':')[0];
  404. if (!bucketName) {
  405. throw new _errors.QiniuError(_errors.QiniuErrorName.InvalidToken, 'resolve bucketName failed.');
  406. }
  407. return {
  408. assessKey: assessKey,
  409. bucketName: bucketName,
  410. scope: putPolicy.scope
  411. };
  412. }
  413. function createObjectURL(file) {
  414. var URL = window.URL || window.webkitURL || window.mozURL; // FIXME: 需要 revokeObjectURL
  415. return URL.createObjectURL(file);
  416. }