object-storage-js
Version:
Object storage SDK for browser — supports server upload, MinIO, OBS, OSS, AWS S3, Qiniu Kodo, and Baidu BOS
9 lines (8 loc) • 13.9 kB
JavaScript
/*!
* object-storage-js v0.0.4
* Object storage SDK for browser — supports server upload, MinIO, OBS, OSS, AWS S3, Qiniu Kodo, and Baidu BOS
* https://gitee.com/lilele01/object-storage-js
* Released under the MIT License.
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ObjectStorage={})}(this,function(e){"use strict";var t;e.ObjectStorageType=void 0,(t=e.ObjectStorageType||(e.ObjectStorageType={})).NORMAL="normal",t.OSS="oss",t.OBS="obs",t.MINIO="minio",t.AWS="aws",t.QINIU="qiniu",t.BOS="bos";function r(e){if(!e)throw new Error("ObjectStorage: file is required");return e}function n(e){const t=null==e?void 0:e.trim();if(!t)throw new Error("ObjectStorage: bucketName is required");return t}function o(e){var t,r;const n=(null===(t=e.fileName)||void 0===t?void 0:t.trim())||(null===(r=e.file.name)||void 0===r?void 0:r.trim());if(!n)throw new Error("ObjectStorage: fileName could not be resolved");return n}function a(e,t){return Number.isFinite(t)&&t>0&&e.size>t}function s(e){if(null==e)return 5242880;if(!Number.isFinite(e)||e<=0)throw new Error("ObjectStorage: partSize must be a positive number");return Math.floor(e)}function i(e){if(null==e)return 4;if(!Number.isFinite(e)||e<=0)throw new Error("ObjectStorage: concurrency must be a positive number");return Math.floor(e)}function l(e){const t={instance:null,cancel(){var e;null===(e=t.instance)||void 0===e||e.abort()}};return null==e||e(t),t}function c(e,t){const r=Math.max(Math.floor(e),0),n=Math.max(Math.floor(t),0),o=n>0?Math.min(r,n):r;return{loaded:o,total:n,percent:n>0?Number((o/n*100).toFixed(2)):0}}async function u(e,t,r){if(0===e.length)return;let n=0;const o=Array.from({length:Math.min(Math.max(t,1),e.length)},()=>async function(){for(;n<e.length;){const t=n++;await r(e[t],t)}}());await Promise.all(o)}function d(e,t,l){const d=e,h=r(t.file),b=n(l),f=o(t);return a(h,t.maxSize)?async function(e,t,r,n,o){var a,l,d,h;const b=s(o.partSize),f=i(o.queueLength),g=function(e,t){const r=[];let n=0,o=1;for(;n<e.size;){const a=Math.min(n+t,e.size);r.push({partNumber:o,start:n,end:a,size:a-n}),n=a,o+=1}return r}(t,b),m=[],y={"Content-Type":o.contentType||t.type||void 0,...null!==(a=o.sdkUploadParams)&&void 0!==a?a:{}};let S="",v=0,O=!1;const w={instance:null,cancel(){O=!0,S&&e.abortMultipartUpload&&e.abortMultipartUpload(n,r,S)}};null===(l=o.onCancel)||void 0===l||l.call(o,w);try{const a=await e.initiateMultipartUpload(n,r,y);if(S=null!==(h=null===(d=a.body)||void 0===d?void 0:d.uploadId)&&void 0!==h?h:"",!S)throw new Error("ObjectStorage: failed to initiate Baidu BOS multipart upload");if(await u(g,f,async a=>{var s;if(O)throw new Error("ObjectStorage: Baidu BOS multipart upload canceled");const i=t.slice(a.start,a.end),l=await e.uploadPartFromBlob(n,r,S,a.partNumber,a.size,i);m.push({partNumber:a.partNumber,eTag:p(l)}),v+=a.size,null===(s=o.onUploadProgress)||void 0===s||s.call(o,c(v,t.size))}),O)throw new Error("ObjectStorage: Baidu BOS multipart upload canceled");return e.completeMultipartUpload(n,r,S,m.sort((e,t)=>e.partNumber-t.partNumber))}catch(t){throw S&&e.abortMultipartUpload&&await e.abortMultipartUpload(n,r,S),t}}(d,h,f,b,t):function(e,t,r,n,o){var a;return e.on("progress",e=>{var r,n,a;!1!==e.lengthComputable&&(null===(r=o.onUploadProgress)||void 0===r||r.call(o,c(null!==(n=e.loaded)&&void 0!==n?n:0,null!==(a=e.total)&&void 0!==a?a:t.size)))}),e.putObjectFromBlob(n,r,t,{"Content-Type":o.contentType||t.type||void 0,...null!==(a=o.sdkUploadParams)&&void 0!==a?a:{}})}(d,h,f,b,t)}function p(e){var t,r,n,o,a,s,i;const l=null!==(r=null!==(t=e.http_headers)&&void 0!==t?t:e.httpHeaders)&&void 0!==r?r:e.headers,c=null!==(s=null!==(o=null!==(n=null==l?void 0:l.etag)&&void 0!==n?n:null==l?void 0:l.ETag)&&void 0!==o?o:null===(a=e.body)||void 0===a?void 0:a.eTag)&&void 0!==s?s:null===(i=e.body)||void 0===i?void 0:i.etag;if(!c)throw new Error("ObjectStorage: failed to resolve Baidu BOS part ETag");return c}function h(e,t){var r;const n=function(e){if(null==e||"object"!=typeof e)throw new Error('ObjectStorage: sdkObject is required for type "bos"');return e}(e),o=new n.BosClient({endpoint:t.endPoint,credentials:{ak:t.accessKey,sk:t.secretKey},...null!==(r=t.sdkOtherParams)&&void 0!==r?r:{}});return t.signatureUrl&&(o.createSignature=function(e,t){return(r,n,o,a,s)=>{var i;const l=null===(i=e.Q)||void 0===i?void 0:i.defer();if(!l)throw new Error("ObjectStorage: Baidu BOS SDK Q.defer is required");const c=new XMLHttpRequest;return c.open("POST",t,!0),c.setRequestHeader("Content-Type","application/json"),c.onload=()=>{c.status>=200&&c.status<300?l.resolve(c.responseText):l.reject(new Error(`ObjectStorage: Baidu BOS signature failed with status ${c.status}`))},c.onerror=()=>{l.reject(new Error("ObjectStorage: Baidu BOS signature network error"))},c.send(JSON.stringify({httpMethod:n,path:o,params:a,headers:s})),l.promise}}(n,t.signatureUrl)),o}class b extends Error{constructor(e,t){super(e),this.name="HttpRequestError",this.status=t.status,this.statusText=t.statusText,this.responseText=t.responseText,this.url=t.url,this.isAborted=Boolean(t.isAborted)}}function f(e){return new Promise((t,r)=>{var n;const o=new XMLHttpRequest;!function(e,t){e&&"object"==typeof e&&(e.instance=t)}(e.xhrInstance,o),o.open(e.method,e.url,!0),o.upload.onprogress=t=>{e.onProgress&&t.lengthComputable&&e.onProgress(c(t.loaded,t.total))},o.onabort=()=>{g(e.xhrInstance,o),r(new b("Request aborted",{url:e.url,status:o.status,statusText:o.statusText,responseText:o.responseText,isAborted:!0}))},o.onload=()=>{g(e.xhrInstance,o),o.status>=200&&o.status<300?t(o.responseText):r(new b(`Request failed with status ${o.status}`,{url:e.url,status:o.status,statusText:o.statusText,responseText:o.responseText}))},o.onerror=()=>{g(e.xhrInstance,o),r(new b("Network error",{url:e.url,status:o.status,statusText:o.statusText,responseText:o.responseText}))},o.send(null!==(n=e.data)&&void 0!==n?n:null)})}function g(e,t){(null==e?void 0:e.instance)===t&&(e.instance=null)}async function m(e){const t=r(e.file),{uploadUrl:n="",mergeUrl:d=""}=e;if(!n)throw new Error("ObjectStorage: uploadUrl is required for normal upload");const p=o(e);return a(t,e.maxSize)?async function(e,t,r,n,o){var a;if(!n)throw new Error("ObjectStorage: mergeUrl is required for multipart upload");const d=s(o.partSize),p=i(o.queueLength),h=Math.ceil(e.size/d),b=function(){var e,t,r;return null!==(r=null===(t=null===(e=globalThis.crypto)||void 0===e?void 0:e.randomUUID)||void 0===t?void 0:t.call(e))&&void 0!==r?r:`${Date.now()}-${Math.floor(1e6*Math.random())}`}(),g=l();let m=0;const y=[],S={instance:null,cancel(){y.forEach(e=>e.abortHandle.cancel()),g.cancel()}};null===(a=o.onCancel)||void 0===a||a.call(o,S);for(let t=1;t<=h;t++){const r=(t-1)*d,n=Math.min(r+d,e.size),o=e.slice(r,n);y.push({index:t,blob:o,size:o.size,loaded:0,uploadId:b,abortHandle:l()})}const v=()=>{var t;null===(t=o.onUploadProgress)||void 0===t||t.call(o,c(m,e.size))};try{await u(y,p,async e=>{const n=new FormData;n.append("file",e.blob),n.append("uploadId",e.uploadId),n.append("chunk",e.index.toString()),n.append("chunks",h.toString()),n.append("fileName",t),await f({url:r,method:"post",data:n,xhrInstance:e.abortHandle,onProgress:t=>{const r=Math.min(t.loaded,e.size);r!==e.loaded&&(m+=r-e.loaded,e.loaded=r,v())}}),e.loaded!==e.size&&(m+=e.size-e.loaded,e.loaded=e.size,v())})}catch(e){throw S.cancel(),e}const O=new URLSearchParams({uploadId:b,fileName:t});return f({url:`${n}?${O.toString()}`,method:"get",xhrInstance:g})}(t,p,n,d,e):async function(e,t,r,n){const o=l(n.onCancel),a=new FormData;return a.append("file",e),a.append("fileName",t),f({url:r,method:"post",data:a,onProgress:n.onUploadProgress,xhrInstance:o})}(t,p,n,e)}async function y(e,t,u){const d=e,p=r(t.file),h=n(u),b=o(t);return a(p,t.maxSize)?function(e,t,r,n,o){const a=s(o.partSize),l=i(o.queueLength);return new Promise((s,i)=>{e.uploadFile({Bucket:n,Key:r,SourceFile:t,PartSize:a,TaskNum:l,ProgressCallback(e,t){var r;null===(r=o.onUploadProgress)||void 0===r||r.call(o,c(e,t))},ResumeCallback(e){var t;const r=e;null===(t=o.onCancel)||void 0===t||t.call(o,{instance:null,cancel:()=>null==r?void 0:r()})}},(e,t)=>{e?i(e):s(t)})})}(d,p,b,h,t):async function(e,t,r,n,o){const a=l(o.onCancel),s=e.createV4SignedUrlSync({Bucket:n,Key:r,Expires:86400,Method:"PUT"});if(!(null==s?void 0:s.SignedUrl))throw new Error("ObjectStorage: failed to generate OBS presigned URL");return f({url:s.SignedUrl,method:"put",data:t,xhrInstance:a,onProgress:o.onUploadProgress})}(d,p,b,h,t)}async function S(e,t,c){const u=e,d=r(t.file),p=n(c),h=o(t);return a(d,t.maxSize)?function(e,t,r,n,o){const a=s(o.partSize),l=i(o.queueLength);return new Promise((o,s)=>{e.upload({Bucket:n,Key:r,Body:t,PartSize:a,QueueSize:l},(e,t)=>{e?s(e):o(t)})})}(u,d,h,p,t):async function(e,t,r,n,o){const a=l(o.onCancel),s=e.getSignedUrl("putObject",{Bucket:n,Key:r,Expires:86400});if(!s)throw new Error("ObjectStorage: failed to generate S3 presigned URL");return f({url:s,method:"put",data:t,xhrInstance:a,onProgress:o.onUploadProgress})}(u,d,h,p,t)}class v{}class O extends v{constructor(){super(...arguments),this.type=e.ObjectStorageType.NORMAL,this.instance=void 0}upload(e){return m(e)}}class w extends v{constructor(t){var r;super(),this.type=e.ObjectStorageType.OBS;const o=null!==(r=t.sdkOtherParams)&&void 0!==r?r:{},a=P(t.sdkObject,e.ObjectStorageType.OBS);this.bucketName=n(t.bucketName),this.instance=new a({...o,access_key_id:t.accessKey,secret_access_key:t.secretKey,server:z(t.endPoint),...t.securityToken?{security_token:t.securityToken}:{}})}upload(e){return y(this.instance,e,this.bucketName)}}class T extends v{constructor(t){var r;super(),this.type=e.ObjectStorageType.OSS;const o=z(t.endPoint),a=null!==(r=t.sdkOtherParams)&&void 0!==r?r:{},s=P(t.sdkObject,e.ObjectStorageType.OSS);this.instance=new s({...a,accessKeyId:t.accessKey,accessKeySecret:t.secretKey,authorizationV4:!0,endpoint:o,bucket:n(t.bucketName),region:N(o,t.region),...t.securityToken?{stsToken:t.securityToken}:{}})}upload(e){return async function(e,t){var n;const l=e,u=r(t.file),d=o(t),p=a(u,t.maxSize);return null===(n=t.onCancel)||void 0===n||n.call(t,{instance:null,cancel:()=>l.cancel()}),l.multipartUpload(d,u,{progress:e=>{var r;null===(r=t.onUploadProgress)||void 0===r||r.call(t,c(e*u.size,u.size))},parallel:p?i(t.queueLength):1,partSize:p?s(t.partSize):u.size})}(this.instance,e)}cancel(){var e;const t=this.instance;null===(e=t.cancel)||void 0===e||e.call(t)}}class k extends v{constructor(t){var r;super();const o=null!==(r=t.sdkOtherParams)&&void 0!==r?r:{},a=P(t.sdkObject,t.type);this.type=t.type,this.bucketName=n(t.bucketName),this.instance=new a.S3({...o,accessKeyId:t.accessKey,secretAccessKey:t.secretKey,endpoint:t.endPoint,region:t.region,signatureVersion:"v4",...t.type===e.ObjectStorageType.MINIO?{s3ForcePathStyle:!0}:{},...t.securityToken?{sessionToken:t.securityToken}:{}})}upload(e){return S(this.instance,e,this.bucketName)}}class j extends v{constructor(t){var r;super(),this.type=e.ObjectStorageType.QINIU,this.instance=P(t.sdkObject,e.ObjectStorageType.QINIU),this.uploadToken=t.uploadToken,this.sdkOtherParams=null!==(r=t.sdkOtherParams)&&void 0!==r?r:{}}upload(e){return function(e,t,n,l={}){var u;const d=e,p=r(t.file),h=o(t),b=t.uploadToken||n;if(!b)throw new Error("ObjectStorage: uploadToken is required for qiniu upload");const f=a(p,t.maxSize),g={fname:p.name,mimeType:t.contentType||p.type||void 0,...null!==(u=t.sdkUploadParams)&&void 0!==u?u:{}},m={...l,...t.maxSize?{forceDirect:!f}:{},chunkSize:(y=s(t.partSize),Math.max(1,Math.ceil(y/1024/1024))),concurrentRequestLimit:i(t.queueLength)};var y;return new Promise((e,r)=>{var n;let o=null;const a={instance:null,cancel(){null==o||o.unsubscribe()}};o=d.upload(p,h,b,g,m).subscribe({next(e){var r,n,o,a,s;const i=null!==(n=null===(r=e.total)||void 0===r?void 0:r.total)&&void 0!==n?n:p.size,l=null!==(a=null===(o=e.total)||void 0===o?void 0:o.loaded)&&void 0!==a?a:0;null===(s=t.onUploadProgress)||void 0===s||s.call(t,c(l,i))},error(e){r(e)},complete(t){e(t)}}),null===(n=t.onCancel)||void 0===n||n.call(t,a)})}(this.instance,e,this.uploadToken,this.sdkOtherParams)}}class x extends v{constructor(t){super(),this.type=e.ObjectStorageType.BOS,this.bucketName=n(t.bucketName),this.instance=h(t.sdkObject,{accessKey:t.accessKey,secretKey:t.secretKey,endPoint:z(t.endPoint),signatureUrl:t.signatureUrl,sdkOtherParams:t.sdkOtherParams})}upload(e){return d(this.instance,e,this.bucketName)}}function P(e,t){if(null==e)throw new Error(`ObjectStorage: sdkObject is required for type "${t}"`);return e}function z(e){const t=null==e?void 0:e.trim();if(!t)throw new Error("ObjectStorage: endPoint is required");return t}function N(e,t){if(t)return t;const r=e.match(/https?:\/\/([a-zA-Z0-9-]+)\.aliyuncs\.com/);if(null==r?void 0:r[1])return r[1];throw new Error("ObjectStorage: failed to resolve OSS region from endPoint")}class U{constructor(t){if(!(null==t?void 0:t.type))throw new Error("ObjectStorage: config.type is required");this.adapter=function(t){switch(t.type){case e.ObjectStorageType.NORMAL:return new O;case e.ObjectStorageType.OBS:return new w(t);case e.ObjectStorageType.OSS:return new T(t);case e.ObjectStorageType.MINIO:case e.ObjectStorageType.AWS:return new k(t);case e.ObjectStorageType.QINIU:return new j(t);case e.ObjectStorageType.BOS:return new x(t);default:throw new Error(`ObjectStorage: unsupported type "${t.type}"`)}}(t),this.instance=this.adapter.instance,this.bucketName="bucketName"in t?t.bucketName:void 0,this.uploadType=t.type}upload(e){return this.adapter.upload(e)}cancel(){var e,t;null===(t=(e=this.adapter).cancel)||void 0===t||t.call(e)}}e.ObjectStorage=U,e.default=U,Object.defineProperty(e,"__esModule",{value:!0})});
//# sourceMappingURL=index.umd.js.map