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.3 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.
*/
var e;!function(e){e.NORMAL="normal",e.OSS="oss",e.OBS="obs",e.MINIO="minio",e.AWS="aws",e.QINIU="qiniu",e.BOS="bos"}(e||(e={}));function t(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 r(e){var t,n;const r=(null===(t=e.fileName)||void 0===t?void 0:t.trim())||(null===(n=e.file.name)||void 0===n?void 0:n.trim());if(!r)throw new Error("ObjectStorage: fileName could not be resolved");return r}function o(e,t){return Number.isFinite(t)&&t>0&&e.size>t}function a(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 s(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 i(e){const t={instance:null,cancel(){var e;null===(e=t.instance)||void 0===e||e.abort()}};return null==e||e(t),t}function l(e,t){const n=Math.max(Math.floor(e),0),r=Math.max(Math.floor(t),0),o=r>0?Math.min(n,r):n;return{loaded:o,total:r,percent:r>0?Number((o/r*100).toFixed(2)):0}}async function u(e,t,n){if(0===e.length)return;let r=0;const o=Array.from({length:Math.min(Math.max(t,1),e.length)},()=>async function(){for(;r<e.length;){const t=r++;await n(e[t],t)}}());await Promise.all(o)}function c(e,i,c){const p=e,h=t(i.file),m=n(c),f=r(i);return o(h,i.maxSize)?async function(e,t,n,r,o){var i,c,p,h;const m=a(o.partSize),f=s(o.queueLength),v=function(e,t){const n=[];let r=0,o=1;for(;r<e.size;){const a=Math.min(r+t,e.size);n.push({partNumber:o,start:r,end:a,size:a-r}),r=a,o+=1}return n}(t,m),b=[],g={"Content-Type":o.contentType||t.type||void 0,...null!==(i=o.sdkUploadParams)&&void 0!==i?i:{}};let S="",y=0,w=!1;const O={instance:null,cancel(){w=!0,S&&e.abortMultipartUpload&&e.abortMultipartUpload(r,n,S)}};null===(c=o.onCancel)||void 0===c||c.call(o,O);try{const a=await e.initiateMultipartUpload(r,n,g);if(S=null!==(h=null===(p=a.body)||void 0===p?void 0:p.uploadId)&&void 0!==h?h:"",!S)throw new Error("ObjectStorage: failed to initiate Baidu BOS multipart upload");if(await u(v,f,async a=>{var s;if(w)throw new Error("ObjectStorage: Baidu BOS multipart upload canceled");const i=t.slice(a.start,a.end),u=await e.uploadPartFromBlob(r,n,S,a.partNumber,a.size,i);b.push({partNumber:a.partNumber,eTag:d(u)}),y+=a.size,null===(s=o.onUploadProgress)||void 0===s||s.call(o,l(y,t.size))}),w)throw new Error("ObjectStorage: Baidu BOS multipart upload canceled");return e.completeMultipartUpload(r,n,S,b.sort((e,t)=>e.partNumber-t.partNumber))}catch(t){throw S&&e.abortMultipartUpload&&await e.abortMultipartUpload(r,n,S),t}}(p,h,f,m,i):function(e,t,n,r,o){var a;return e.on("progress",e=>{var n,r,a;!1!==e.lengthComputable&&(null===(n=o.onUploadProgress)||void 0===n||n.call(o,l(null!==(r=e.loaded)&&void 0!==r?r:0,null!==(a=e.total)&&void 0!==a?a:t.size)))}),e.putObjectFromBlob(r,n,t,{"Content-Type":o.contentType||t.type||void 0,...null!==(a=o.sdkUploadParams)&&void 0!==a?a:{}})}(p,h,f,m,i)}function d(e){var t,n,r,o,a,s,i;const l=null!==(n=null!==(t=e.http_headers)&&void 0!==t?t:e.httpHeaders)&&void 0!==n?n:e.headers,u=null!==(s=null!==(o=null!==(r=null==l?void 0:l.etag)&&void 0!==r?r: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(!u)throw new Error("ObjectStorage: failed to resolve Baidu BOS part ETag");return u}function p(e,t){var n;const r=function(e){if(null==e||"object"!=typeof e)throw new Error('ObjectStorage: sdkObject is required for type "bos"');return e}(e),o=new r.BosClient({endpoint:t.endPoint,credentials:{ak:t.accessKey,sk:t.secretKey},...null!==(n=t.sdkOtherParams)&&void 0!==n?n:{}});return t.signatureUrl&&(o.createSignature=function(e,t){return(n,r,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 u=new XMLHttpRequest;return u.open("POST",t,!0),u.setRequestHeader("Content-Type","application/json"),u.onload=()=>{u.status>=200&&u.status<300?l.resolve(u.responseText):l.reject(new Error(`ObjectStorage: Baidu BOS signature failed with status ${u.status}`))},u.onerror=()=>{l.reject(new Error("ObjectStorage: Baidu BOS signature network error"))},u.send(JSON.stringify({httpMethod:r,path:o,params:a,headers:s})),l.promise}}(r,t.signatureUrl)),o}class h 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 m(e){return new Promise((t,n)=>{var r;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(l(t.loaded,t.total))},o.onabort=()=>{f(e.xhrInstance,o),n(new h("Request aborted",{url:e.url,status:o.status,statusText:o.statusText,responseText:o.responseText,isAborted:!0}))},o.onload=()=>{f(e.xhrInstance,o),o.status>=200&&o.status<300?t(o.responseText):n(new h(`Request failed with status ${o.status}`,{url:e.url,status:o.status,statusText:o.statusText,responseText:o.responseText}))},o.onerror=()=>{f(e.xhrInstance,o),n(new h("Network error",{url:e.url,status:o.status,statusText:o.statusText,responseText:o.responseText}))},o.send(null!==(r=e.data)&&void 0!==r?r:null)})}function f(e,t){(null==e?void 0:e.instance)===t&&(e.instance=null)}async function v(e){const n=t(e.file),{uploadUrl:c="",mergeUrl:d=""}=e;if(!c)throw new Error("ObjectStorage: uploadUrl is required for normal upload");const p=r(e);return o(n,e.maxSize)?async function(e,t,n,r,o){var c;if(!r)throw new Error("ObjectStorage: mergeUrl is required for multipart upload");const d=a(o.partSize),p=s(o.queueLength),h=Math.ceil(e.size/d),f=function(){var e,t,n;return null!==(n=null===(t=null===(e=globalThis.crypto)||void 0===e?void 0:e.randomUUID)||void 0===t?void 0:t.call(e))&&void 0!==n?n:`${Date.now()}-${Math.floor(1e6*Math.random())}`}(),v=i();let b=0;const g=[],S={instance:null,cancel(){g.forEach(e=>e.abortHandle.cancel()),v.cancel()}};null===(c=o.onCancel)||void 0===c||c.call(o,S);for(let t=1;t<=h;t++){const n=(t-1)*d,r=Math.min(n+d,e.size),o=e.slice(n,r);g.push({index:t,blob:o,size:o.size,loaded:0,uploadId:f,abortHandle:i()})}const y=()=>{var t;null===(t=o.onUploadProgress)||void 0===t||t.call(o,l(b,e.size))};try{await u(g,p,async e=>{const r=new FormData;r.append("file",e.blob),r.append("uploadId",e.uploadId),r.append("chunk",e.index.toString()),r.append("chunks",h.toString()),r.append("fileName",t),await m({url:n,method:"post",data:r,xhrInstance:e.abortHandle,onProgress:t=>{const n=Math.min(t.loaded,e.size);n!==e.loaded&&(b+=n-e.loaded,e.loaded=n,y())}}),e.loaded!==e.size&&(b+=e.size-e.loaded,e.loaded=e.size,y())})}catch(e){throw S.cancel(),e}const w=new URLSearchParams({uploadId:f,fileName:t});return m({url:`${r}?${w.toString()}`,method:"get",xhrInstance:v})}(n,p,c,d,e):async function(e,t,n,r){const o=i(r.onCancel),a=new FormData;return a.append("file",e),a.append("fileName",t),m({url:n,method:"post",data:a,onProgress:r.onUploadProgress,xhrInstance:o})}(n,p,c,e)}async function b(e,u,c){const d=e,p=t(u.file),h=n(c),f=r(u);return o(p,u.maxSize)?function(e,t,n,r,o){const i=a(o.partSize),u=s(o.queueLength);return new Promise((a,s)=>{e.uploadFile({Bucket:r,Key:n,SourceFile:t,PartSize:i,TaskNum:u,ProgressCallback(e,t){var n;null===(n=o.onUploadProgress)||void 0===n||n.call(o,l(e,t))},ResumeCallback(e){var t;const n=e;null===(t=o.onCancel)||void 0===t||t.call(o,{instance:null,cancel:()=>null==n?void 0:n()})}},(e,t)=>{e?s(e):a(t)})})}(d,p,f,h,u):async function(e,t,n,r,o){const a=i(o.onCancel),s=e.createV4SignedUrlSync({Bucket:r,Key:n,Expires:86400,Method:"PUT"});if(!(null==s?void 0:s.SignedUrl))throw new Error("ObjectStorage: failed to generate OBS presigned URL");return m({url:s.SignedUrl,method:"put",data:t,xhrInstance:a,onProgress:o.onUploadProgress})}(d,p,f,h,u)}async function g(e,l,u){const c=e,d=t(l.file),p=n(u),h=r(l);return o(d,l.maxSize)?function(e,t,n,r,o){const i=a(o.partSize),l=s(o.queueLength);return new Promise((o,a)=>{e.upload({Bucket:r,Key:n,Body:t,PartSize:i,QueueSize:l},(e,t)=>{e?a(e):o(t)})})}(c,d,h,p,l):async function(e,t,n,r,o){const a=i(o.onCancel),s=e.getSignedUrl("putObject",{Bucket:r,Key:n,Expires:86400});if(!s)throw new Error("ObjectStorage: failed to generate S3 presigned URL");return m({url:s,method:"put",data:t,xhrInstance:a,onProgress:o.onUploadProgress})}(c,d,h,p,l)}class S{}class y extends S{constructor(){super(...arguments),this.type=e.NORMAL,this.instance=void 0}upload(e){return v(e)}}class w extends S{constructor(t){var r;super(),this.type=e.OBS;const o=null!==(r=t.sdkOtherParams)&&void 0!==r?r:{},a=T(t.sdkObject,e.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 b(this.instance,e,this.bucketName)}}class O extends S{constructor(t){var r;super(),this.type=e.OSS;const o=z(t.endPoint),a=null!==(r=t.sdkOtherParams)&&void 0!==r?r:{},s=T(t.sdkObject,e.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,n){var i;const u=e,c=t(n.file),d=r(n),p=o(c,n.maxSize);return null===(i=n.onCancel)||void 0===i||i.call(n,{instance:null,cancel:()=>u.cancel()}),u.multipartUpload(d,c,{progress:e=>{var t;null===(t=n.onUploadProgress)||void 0===t||t.call(n,l(e*c.size,c.size))},parallel:p?s(n.queueLength):1,partSize:p?a(n.partSize):c.size})}(this.instance,e)}cancel(){var e;const t=this.instance;null===(e=t.cancel)||void 0===e||e.call(t)}}class k extends S{constructor(t){var r;super();const o=null!==(r=t.sdkOtherParams)&&void 0!==r?r:{},a=T(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.MINIO?{s3ForcePathStyle:!0}:{},...t.securityToken?{sessionToken:t.securityToken}:{}})}upload(e){return g(this.instance,e,this.bucketName)}}class x extends S{constructor(t){var n;super(),this.type=e.QINIU,this.instance=T(t.sdkObject,e.QINIU),this.uploadToken=t.uploadToken,this.sdkOtherParams=null!==(n=t.sdkOtherParams)&&void 0!==n?n:{}}upload(e){return function(e,n,i,u={}){var c;const d=e,p=t(n.file),h=r(n),m=n.uploadToken||i;if(!m)throw new Error("ObjectStorage: uploadToken is required for qiniu upload");const f=o(p,n.maxSize),v={fname:p.name,mimeType:n.contentType||p.type||void 0,...null!==(c=n.sdkUploadParams)&&void 0!==c?c:{}},b={...u,...n.maxSize?{forceDirect:!f}:{},chunkSize:(g=a(n.partSize),Math.max(1,Math.ceil(g/1024/1024))),concurrentRequestLimit:s(n.queueLength)};var g;return new Promise((e,t)=>{var r;let o=null;const a={instance:null,cancel(){null==o||o.unsubscribe()}};o=d.upload(p,h,m,v,b).subscribe({next(e){var t,r,o,a,s;const i=null!==(r=null===(t=e.total)||void 0===t?void 0:t.total)&&void 0!==r?r:p.size,u=null!==(a=null===(o=e.total)||void 0===o?void 0:o.loaded)&&void 0!==a?a:0;null===(s=n.onUploadProgress)||void 0===s||s.call(n,l(u,i))},error(e){t(e)},complete(t){e(t)}}),null===(r=n.onCancel)||void 0===r||r.call(n,a)})}(this.instance,e,this.uploadToken,this.sdkOtherParams)}}class P extends S{constructor(t){super(),this.type=e.BOS,this.bucketName=n(t.bucketName),this.instance=p(t.sdkObject,{accessKey:t.accessKey,secretKey:t.secretKey,endPoint:z(t.endPoint),signatureUrl:t.signatureUrl,sdkOtherParams:t.sdkOtherParams})}upload(e){return c(this.instance,e,this.bucketName)}}function T(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 n=e.match(/https?:\/\/([a-zA-Z0-9-]+)\.aliyuncs\.com/);if(null==n?void 0:n[1])return n[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.NORMAL:return new y;case e.OBS:return new w(t);case e.OSS:return new O(t);case e.MINIO:case e.AWS:return new k(t);case e.QINIU:return new x(t);case e.BOS:return new P(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)}}export{U as ObjectStorage,e as ObjectStorageType,U as default};
//# sourceMappingURL=index.esm.js.map