租房小程序前端代码
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.

272 lines
8.5 KiB

3 months ago
  1. const copy = require('copy-to');
  2. const callback = require('./callback');
  3. const { deepCopyWith } = require('./utils/deepCopy');
  4. const { isBuffer } = require('./utils/isBuffer');
  5. const { omit } = require('./utils/omit');
  6. const proto = exports;
  7. /**
  8. * List the on-going multipart uploads
  9. * https://help.aliyun.com/document_detail/31997.html
  10. * @param {Object} options
  11. * @return {Array} the multipart uploads
  12. */
  13. proto.listUploads = async function listUploads(query, options) {
  14. options = options || {};
  15. const opt = {};
  16. copy(options).to(opt);
  17. opt.subres = 'uploads';
  18. const params = this._objectRequestParams('GET', '', opt);
  19. params.query = query;
  20. params.xmlResponse = true;
  21. params.successStatuses = [200];
  22. const result = await this.request(params);
  23. let uploads = result.data.Upload || [];
  24. if (!Array.isArray(uploads)) {
  25. uploads = [uploads];
  26. }
  27. uploads = uploads.map(up => ({
  28. name: up.Key,
  29. uploadId: up.UploadId,
  30. initiated: up.Initiated
  31. }));
  32. return {
  33. res: result.res,
  34. uploads,
  35. bucket: result.data.Bucket,
  36. nextKeyMarker: result.data.NextKeyMarker,
  37. nextUploadIdMarker: result.data.NextUploadIdMarker,
  38. isTruncated: result.data.IsTruncated === 'true'
  39. };
  40. };
  41. /**
  42. * List the done uploadPart parts
  43. * @param {String} name object name
  44. * @param {String} uploadId multipart upload id
  45. * @param {Object} query
  46. * {Number} query.max-parts The maximum part number in the response of the OSS. Default value: 1000
  47. * {Number} query.part-number-marker Starting position of a specific list.
  48. * {String} query.encoding-type Specify the encoding of the returned content and the encoding type.
  49. * @param {Object} options
  50. * @return {Object} result
  51. */
  52. proto.listParts = async function listParts(name, uploadId, query, options) {
  53. options = options || {};
  54. const opt = {};
  55. copy(options).to(opt);
  56. opt.subres = {
  57. uploadId
  58. };
  59. const params = this._objectRequestParams('GET', name, opt);
  60. params.query = query;
  61. params.xmlResponse = true;
  62. params.successStatuses = [200];
  63. const result = await this.request(params);
  64. return {
  65. res: result.res,
  66. uploadId: result.data.UploadId,
  67. bucket: result.data.Bucket,
  68. name: result.data.Key,
  69. partNumberMarker: result.data.PartNumberMarker,
  70. nextPartNumberMarker: result.data.NextPartNumberMarker,
  71. maxParts: result.data.MaxParts,
  72. isTruncated: result.data.IsTruncated,
  73. parts: result.data.Part || []
  74. };
  75. };
  76. /**
  77. * Abort a multipart upload transaction
  78. * @param {String} name the object name
  79. * @param {String} uploadId the upload id
  80. * @param {Object} options
  81. */
  82. proto.abortMultipartUpload = async function abortMultipartUpload(name, uploadId, options) {
  83. this._stop();
  84. options = options || {};
  85. const opt = {};
  86. copy(options).to(opt);
  87. opt.subres = { uploadId };
  88. const params = this._objectRequestParams('DELETE', name, opt);
  89. params.successStatuses = [204];
  90. const result = await this.request(params);
  91. return {
  92. res: result.res
  93. };
  94. };
  95. /**
  96. * Initiate a multipart upload transaction
  97. * @param {String} name the object name
  98. * @param {Object} options
  99. * @return {String} upload id
  100. */
  101. proto.initMultipartUpload = async function initMultipartUpload(name, options) {
  102. options = options || {};
  103. const opt = {};
  104. copy(options).to(opt);
  105. opt.headers = opt.headers || {};
  106. this._convertMetaToHeaders(options.meta, opt.headers);
  107. opt.subres = 'uploads';
  108. const params = this._objectRequestParams('POST', name, opt);
  109. params.mime = options.mime;
  110. params.xmlResponse = true;
  111. params.successStatuses = [200];
  112. const result = await this.request(params);
  113. return {
  114. res: result.res,
  115. bucket: result.data.Bucket,
  116. name: result.data.Key,
  117. uploadId: result.data.UploadId
  118. };
  119. };
  120. /**
  121. * Upload a part in a multipart upload transaction
  122. * @param {String} name the object name
  123. * @param {String} uploadId the upload id
  124. * @param {Integer} partNo the part number
  125. * @param {File} file upload File, whole File
  126. * @param {Integer} start part start bytes e.g: 102400
  127. * @param {Integer} end part end bytes e.g: 204800
  128. * @param {Object} options
  129. */
  130. proto.uploadPart = async function uploadPart(name, uploadId, partNo, file, start, end, options) {
  131. const data = {
  132. size: end - start
  133. };
  134. const isBrowserEnv = process && process.browser;
  135. isBrowserEnv
  136. ? (data.content = await this._createBuffer(file, start, end))
  137. : (data.stream = await this._createStream(file, start, end));
  138. return await this._uploadPart(name, uploadId, partNo, data, options);
  139. };
  140. /**
  141. * Complete a multipart upload transaction
  142. * @param {String} name the object name
  143. * @param {String} uploadId the upload id
  144. * @param {Array} parts the uploaded parts, each in the structure:
  145. * {Integer} number partNo
  146. * {String} etag part etag uploadPartCopy result.res.header.etag
  147. * @param {Object} options
  148. * {Object} [options.callback] The callback parameter is composed of a JSON string encoded in Base64
  149. * {String} options.callback.url the OSS sends a callback request to this URL
  150. * {String} [options.callback.host] The host header value for initiating callback requests
  151. * {String} options.callback.body The value of the request body when a callback is initiated
  152. * {String} [options.callback.contentType] The Content-Type of the callback requests initiated
  153. * {Boolean} [options.callback.callbackSNI] Whether OSS sends SNI to the origin address specified by callbackUrl when a callback request is initiated from the client
  154. * {Object} [options.callback.customValue] Custom parameters are a map of key-values, e.g:
  155. * customValue = {
  156. * key1: 'value1',
  157. * key2: 'value2'
  158. * }
  159. */
  160. proto.completeMultipartUpload = async function completeMultipartUpload(name, uploadId, parts, options) {
  161. const completeParts = parts
  162. .concat()
  163. .sort((a, b) => a.number - b.number)
  164. .filter((item, index, arr) => !index || item.number !== arr[index - 1].number);
  165. let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<CompleteMultipartUpload>\n';
  166. for (let i = 0; i < completeParts.length; i++) {
  167. const p = completeParts[i];
  168. xml += '<Part>\n';
  169. xml += `<PartNumber>${p.number}</PartNumber>\n`;
  170. xml += `<ETag>${p.etag}</ETag>\n`;
  171. xml += '</Part>\n';
  172. }
  173. xml += '</CompleteMultipartUpload>';
  174. options = options || {};
  175. let opt = {};
  176. opt = deepCopyWith(options, _ => {
  177. if (isBuffer(_)) return null;
  178. });
  179. opt.subres = { uploadId };
  180. opt.headers = omit(opt.headers, ['x-oss-server-side-encryption', 'x-oss-storage-class']);
  181. const params = this._objectRequestParams('POST', name, opt);
  182. callback.encodeCallback(params, opt);
  183. params.mime = 'xml';
  184. params.content = xml;
  185. if (!(params.headers && params.headers['x-oss-callback'])) {
  186. params.xmlResponse = true;
  187. }
  188. params.successStatuses = [200];
  189. const result = await this.request(params);
  190. if (options.progress) {
  191. await options.progress(1, null, result.res);
  192. }
  193. const ret = {
  194. res: result.res,
  195. bucket: params.bucket,
  196. name,
  197. etag: result.res.headers.etag
  198. };
  199. if (params.headers && params.headers['x-oss-callback']) {
  200. ret.data = JSON.parse(result.data.toString());
  201. }
  202. return ret;
  203. };
  204. /**
  205. * Upload a part in a multipart upload transaction
  206. * @param {String} name the object name
  207. * @param {String} uploadId the upload id
  208. * @param {Integer} partNo the part number
  209. * @param {Object} data the body data
  210. * @param {Object} options
  211. */
  212. proto._uploadPart = async function _uploadPart(name, uploadId, partNo, data, options) {
  213. options = options || {};
  214. const opt = {};
  215. copy(options).to(opt);
  216. opt.headers = opt.headers || {};
  217. opt.headers['Content-Length'] = data.size;
  218. // Uploading shards does not require x-oss headers.
  219. opt.headers = omit(opt.headers, ['x-oss-server-side-encryption', 'x-oss-storage-class']);
  220. opt.subres = {
  221. partNumber: partNo,
  222. uploadId
  223. };
  224. const params = this._objectRequestParams('PUT', name, opt);
  225. params.mime = opt.mime;
  226. const isBrowserEnv = process && process.browser;
  227. isBrowserEnv ? (params.content = data.content) : (params.stream = data.stream);
  228. params.successStatuses = [200];
  229. params.disabledMD5 = options.disabledMD5;
  230. const result = await this.request(params);
  231. if (!result.res.headers.etag) {
  232. throw new Error(
  233. 'Please set the etag of expose-headers in OSS \n https://help.aliyun.com/document_detail/32069.html'
  234. );
  235. }
  236. if (data.stream) {
  237. data.stream = null;
  238. params.stream = null;
  239. }
  240. return {
  241. name,
  242. etag: result.res.headers.etag,
  243. res: result.res
  244. };
  245. };