helper.js 12 KB

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