@bedelightful/upload-sdk 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/README.md +132 -0
- package/dist/es/Exception/BaseException.js +14 -0
- package/dist/es/Exception/BaseException.js.map +1 -0
- package/dist/es/Exception/DownloadException.js +40 -0
- package/dist/es/Exception/DownloadException.js.map +1 -0
- package/dist/es/Exception/HttpException.js +50 -0
- package/dist/es/Exception/HttpException.js.map +1 -0
- package/dist/es/Exception/InitException.js +49 -0
- package/dist/es/Exception/InitException.js.map +1 -0
- package/dist/es/Exception/UploadException.js +50 -0
- package/dist/es/Exception/UploadException.js.map +1 -0
- package/dist/es/index.d.ts +867 -0
- package/dist/es/index.js +162 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/modules/Kodo/defaultUpload.js +38 -0
- package/dist/es/modules/Kodo/defaultUpload.js.map +1 -0
- package/dist/es/modules/Kodo/index.js +8 -0
- package/dist/es/modules/Kodo/index.js.map +1 -0
- package/dist/es/modules/Local/index.js +31 -0
- package/dist/es/modules/Local/index.js.map +1 -0
- package/dist/es/modules/MinIO/MultipartUpload.js +335 -0
- package/dist/es/modules/MinIO/MultipartUpload.js.map +1 -0
- package/dist/es/modules/MinIO/STSUpload.js +10 -0
- package/dist/es/modules/MinIO/STSUpload.js.map +1 -0
- package/dist/es/modules/MinIO/defaultUpload.js +124 -0
- package/dist/es/modules/MinIO/defaultUpload.js.map +1 -0
- package/dist/es/modules/MinIO/index.js +16 -0
- package/dist/es/modules/MinIO/index.js.map +1 -0
- package/dist/es/modules/OBS/MultipartUpload.js +269 -0
- package/dist/es/modules/OBS/MultipartUpload.js.map +1 -0
- package/dist/es/modules/OBS/STSUpload.js +71 -0
- package/dist/es/modules/OBS/STSUpload.js.map +1 -0
- package/dist/es/modules/OBS/defaultUpload.js +59 -0
- package/dist/es/modules/OBS/defaultUpload.js.map +1 -0
- package/dist/es/modules/OBS/index.js +16 -0
- package/dist/es/modules/OBS/index.js.map +1 -0
- package/dist/es/modules/OBS/utils/index.js +25 -0
- package/dist/es/modules/OBS/utils/index.js.map +1 -0
- package/dist/es/modules/OSS/MultipartUpload.js +232 -0
- package/dist/es/modules/OSS/MultipartUpload.js.map +1 -0
- package/dist/es/modules/OSS/STSUpload.js +48 -0
- package/dist/es/modules/OSS/STSUpload.js.map +1 -0
- package/dist/es/modules/OSS/defaultUpload.js +53 -0
- package/dist/es/modules/OSS/defaultUpload.js.map +1 -0
- package/dist/es/modules/OSS/index.js +16 -0
- package/dist/es/modules/OSS/index.js.map +1 -0
- package/dist/es/modules/OSS/utils/helper.js +137 -0
- package/dist/es/modules/OSS/utils/helper.js.map +1 -0
- package/dist/es/modules/OSS/utils/signature.js +96 -0
- package/dist/es/modules/OSS/utils/signature.js.map +1 -0
- package/dist/es/modules/TOS/MultipartUpload.js +288 -0
- package/dist/es/modules/TOS/MultipartUpload.js.map +1 -0
- package/dist/es/modules/TOS/STSUpload.js +92 -0
- package/dist/es/modules/TOS/STSUpload.js.map +1 -0
- package/dist/es/modules/TOS/defaultUpload.js +65 -0
- package/dist/es/modules/TOS/defaultUpload.js.map +1 -0
- package/dist/es/modules/TOS/index.js +16 -0
- package/dist/es/modules/TOS/index.js.map +1 -0
- package/dist/es/modules/TOS/utils/TosClientError.js +15 -0
- package/dist/es/modules/TOS/utils/TosClientError.js.map +1 -0
- package/dist/es/modules/TOS/utils/index.js +38 -0
- package/dist/es/modules/TOS/utils/index.js.map +1 -0
- package/dist/es/modules/TOS/utils/signatureV4.js +269 -0
- package/dist/es/modules/TOS/utils/signatureV4.js.map +1 -0
- package/dist/es/modules/TOS/utils/signatureV4Credentials.js +21 -0
- package/dist/es/modules/TOS/utils/signatureV4Credentials.js.map +1 -0
- package/dist/es/modules/TOS/utils/universal/crypto.browser.js +56 -0
- package/dist/es/modules/TOS/utils/universal/crypto.browser.js.map +1 -0
- package/dist/es/modules/TOS/utils/utils.js +18 -0
- package/dist/es/modules/TOS/utils/utils.js.map +1 -0
- package/dist/es/modules/index.js +20 -0
- package/dist/es/modules/index.js.map +1 -0
- package/dist/es/types/Kodo.js +1 -0
- package/dist/es/types/Kodo.js.map +1 -0
- package/dist/es/types/Local.js +1 -0
- package/dist/es/types/Local.js.map +1 -0
- package/dist/es/types/MinIO.js +1 -0
- package/dist/es/types/MinIO.js.map +1 -0
- package/dist/es/types/OBS.js +8 -0
- package/dist/es/types/OBS.js.map +1 -0
- package/dist/es/types/OSS.js +1 -0
- package/dist/es/types/OSS.js.map +1 -0
- package/dist/es/types/TOS.js +1 -0
- package/dist/es/types/TOS.js.map +1 -0
- package/dist/es/types/error.js +1 -0
- package/dist/es/types/error.js.map +1 -0
- package/dist/es/types/index.js +13 -0
- package/dist/es/types/index.js.map +1 -0
- package/dist/es/types/log.js +1 -0
- package/dist/es/types/log.js.map +1 -0
- package/dist/es/types/request.js +1 -0
- package/dist/es/types/request.js.map +1 -0
- package/dist/es/utils/EventEmitter.js +32 -0
- package/dist/es/utils/EventEmitter.js.map +1 -0
- package/dist/es/utils/UploadManger.js +276 -0
- package/dist/es/utils/UploadManger.js.map +1 -0
- package/dist/es/utils/UploadTask.js +13 -0
- package/dist/es/utils/UploadTask.js.map +1 -0
- package/dist/es/utils/checkDataFormat.js +41 -0
- package/dist/es/utils/checkDataFormat.js.map +1 -0
- package/dist/es/utils/global.js +83 -0
- package/dist/es/utils/global.js.map +1 -0
- package/dist/es/utils/index.js +20 -0
- package/dist/es/utils/index.js.map +1 -0
- package/dist/es/utils/logPubSub.js +59 -0
- package/dist/es/utils/logPubSub.js.map +1 -0
- package/dist/es/utils/multipart.js +159 -0
- package/dist/es/utils/multipart.js.map +1 -0
- package/dist/es/utils/nanoid.js +10 -0
- package/dist/es/utils/nanoid.js.map +1 -0
- package/dist/es/utils/regExpUtil.js +21 -0
- package/dist/es/utils/regExpUtil.js.map +1 -0
- package/dist/es/utils/request.js +234 -0
- package/dist/es/utils/request.js.map +1 -0
- package/dist/es/utils/response.js +20 -0
- package/dist/es/utils/response.js.map +1 -0
- package/dist/index.d.ts +867 -0
- package/dist/index.js +60913 -0
- package/dist/index.js.map +1 -0
- package/dist/index.min.js +130 -0
- package/dist/index.min.js.map +1 -0
- package/dist/lib/Exception/BaseException.js +37 -0
- package/dist/lib/Exception/BaseException.js.map +1 -0
- package/dist/lib/Exception/DownloadException.js +65 -0
- package/dist/lib/Exception/DownloadException.js.map +1 -0
- package/dist/lib/Exception/HttpException.js +75 -0
- package/dist/lib/Exception/HttpException.js.map +1 -0
- package/dist/lib/Exception/InitException.js +73 -0
- package/dist/lib/Exception/InitException.js.map +1 -0
- package/dist/lib/Exception/UploadException.js +75 -0
- package/dist/lib/Exception/UploadException.js.map +1 -0
- package/dist/lib/index.d.cts +867 -0
- package/dist/lib/index.js +203 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/modules/Kodo/defaultUpload.js +61 -0
- package/dist/lib/modules/Kodo/defaultUpload.js.map +1 -0
- package/dist/lib/modules/Kodo/index.js +28 -0
- package/dist/lib/modules/Kodo/index.js.map +1 -0
- package/dist/lib/modules/Local/index.js +50 -0
- package/dist/lib/modules/Local/index.js.map +1 -0
- package/dist/lib/modules/MinIO/MultipartUpload.js +357 -0
- package/dist/lib/modules/MinIO/MultipartUpload.js.map +1 -0
- package/dist/lib/modules/MinIO/STSUpload.js +33 -0
- package/dist/lib/modules/MinIO/STSUpload.js.map +1 -0
- package/dist/lib/modules/MinIO/defaultUpload.js +158 -0
- package/dist/lib/modules/MinIO/defaultUpload.js.map +1 -0
- package/dist/lib/modules/MinIO/index.js +35 -0
- package/dist/lib/modules/MinIO/index.js.map +1 -0
- package/dist/lib/modules/OBS/MultipartUpload.js +296 -0
- package/dist/lib/modules/OBS/MultipartUpload.js.map +1 -0
- package/dist/lib/modules/OBS/STSUpload.js +104 -0
- package/dist/lib/modules/OBS/STSUpload.js.map +1 -0
- package/dist/lib/modules/OBS/defaultUpload.js +88 -0
- package/dist/lib/modules/OBS/defaultUpload.js.map +1 -0
- package/dist/lib/modules/OBS/index.js +45 -0
- package/dist/lib/modules/OBS/index.js.map +1 -0
- package/dist/lib/modules/OBS/utils/index.js +49 -0
- package/dist/lib/modules/OBS/utils/index.js.map +1 -0
- package/dist/lib/modules/OSS/MultipartUpload.js +259 -0
- package/dist/lib/modules/OSS/MultipartUpload.js.map +1 -0
- package/dist/lib/modules/OSS/STSUpload.js +71 -0
- package/dist/lib/modules/OSS/STSUpload.js.map +1 -0
- package/dist/lib/modules/OSS/defaultUpload.js +76 -0
- package/dist/lib/modules/OSS/defaultUpload.js.map +1 -0
- package/dist/lib/modules/OSS/index.js +35 -0
- package/dist/lib/modules/OSS/index.js.map +1 -0
- package/dist/lib/modules/OSS/utils/helper.js +173 -0
- package/dist/lib/modules/OSS/utils/helper.js.map +1 -0
- package/dist/lib/modules/OSS/utils/signature.js +132 -0
- package/dist/lib/modules/OSS/utils/signature.js.map +1 -0
- package/dist/lib/modules/TOS/MultipartUpload.js +315 -0
- package/dist/lib/modules/TOS/MultipartUpload.js.map +1 -0
- package/dist/lib/modules/TOS/STSUpload.js +125 -0
- package/dist/lib/modules/TOS/STSUpload.js.map +1 -0
- package/dist/lib/modules/TOS/defaultUpload.js +94 -0
- package/dist/lib/modules/TOS/defaultUpload.js.map +1 -0
- package/dist/lib/modules/TOS/index.js +45 -0
- package/dist/lib/modules/TOS/index.js.map +1 -0
- package/dist/lib/modules/TOS/utils/TosClientError.js +34 -0
- package/dist/lib/modules/TOS/utils/TosClientError.js.map +1 -0
- package/dist/lib/modules/TOS/utils/index.js +64 -0
- package/dist/lib/modules/TOS/utils/index.js.map +1 -0
- package/dist/lib/modules/TOS/utils/signatureV4.js +294 -0
- package/dist/lib/modules/TOS/utils/signatureV4.js.map +1 -0
- package/dist/lib/modules/TOS/utils/signatureV4Credentials.js +44 -0
- package/dist/lib/modules/TOS/utils/signatureV4Credentials.js.map +1 -0
- package/dist/lib/modules/TOS/utils/universal/crypto.browser.js +93 -0
- package/dist/lib/modules/TOS/utils/universal/crypto.browser.js.map +1 -0
- package/dist/lib/modules/TOS/utils/utils.js +42 -0
- package/dist/lib/modules/TOS/utils/utils.js.map +1 -0
- package/dist/lib/modules/index.js +50 -0
- package/dist/lib/modules/index.js.map +1 -0
- package/dist/lib/types/Kodo.js +17 -0
- package/dist/lib/types/Kodo.js.map +1 -0
- package/dist/lib/types/Local.js +17 -0
- package/dist/lib/types/Local.js.map +1 -0
- package/dist/lib/types/MinIO.js +17 -0
- package/dist/lib/types/MinIO.js.map +1 -0
- package/dist/lib/types/OBS.js +32 -0
- package/dist/lib/types/OBS.js.map +1 -0
- package/dist/lib/types/OSS.js +17 -0
- package/dist/lib/types/OSS.js.map +1 -0
- package/dist/lib/types/TOS.js +17 -0
- package/dist/lib/types/TOS.js.map +1 -0
- package/dist/lib/types/error.js +17 -0
- package/dist/lib/types/error.js.map +1 -0
- package/dist/lib/types/index.js +37 -0
- package/dist/lib/types/index.js.map +1 -0
- package/dist/lib/types/log.js +17 -0
- package/dist/lib/types/log.js.map +1 -0
- package/dist/lib/types/request.js +17 -0
- package/dist/lib/types/request.js.map +1 -0
- package/dist/lib/utils/EventEmitter.js +51 -0
- package/dist/lib/utils/EventEmitter.js.map +1 -0
- package/dist/lib/utils/UploadManger.js +309 -0
- package/dist/lib/utils/UploadManger.js.map +1 -0
- package/dist/lib/utils/UploadTask.js +32 -0
- package/dist/lib/utils/UploadTask.js.map +1 -0
- package/dist/lib/utils/checkDataFormat.js +70 -0
- package/dist/lib/utils/checkDataFormat.js.map +1 -0
- package/dist/lib/utils/global.js +106 -0
- package/dist/lib/utils/global.js.map +1 -0
- package/dist/lib/utils/index.js +44 -0
- package/dist/lib/utils/index.js.map +1 -0
- package/dist/lib/utils/logPubSub.js +78 -0
- package/dist/lib/utils/logPubSub.js.map +1 -0
- package/dist/lib/utils/multipart.js +197 -0
- package/dist/lib/utils/multipart.js.map +1 -0
- package/dist/lib/utils/nanoid.js +33 -0
- package/dist/lib/utils/nanoid.js.map +1 -0
- package/dist/lib/utils/regExpUtil.js +44 -0
- package/dist/lib/utils/regExpUtil.js.map +1 -0
- package/dist/lib/utils/request.js +264 -0
- package/dist/lib/utils/request.js.map +1 -0
- package/dist/lib/utils/response.js +43 -0
- package/dist/lib/utils/response.js.map +1 -0
- package/dist/package.json +120 -0
- package/package.json +120 -0
package/dist/es/index.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { version } from "../package.json";
|
|
4
|
+
import { DownloadException, DownloadExceptionCode } from "./Exception/DownloadException";
|
|
5
|
+
import { InitException, InitExceptionCode } from "./Exception/InitException";
|
|
6
|
+
import PlatformModules from "./modules";
|
|
7
|
+
import { PlatformType } from "./types";
|
|
8
|
+
import { isJson, isObject } from "./utils/checkDataFormat";
|
|
9
|
+
import logPubSub from "./utils/logPubSub";
|
|
10
|
+
import { request } from "./utils/request";
|
|
11
|
+
import { UploadManger } from "./utils/UploadManger";
|
|
12
|
+
import { checkSpecialCharacters, getFileExtension } from "./utils";
|
|
13
|
+
import { nanoid } from "./utils/nanoid";
|
|
14
|
+
const _Upload = class _Upload {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.uploadManger = new UploadManger();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* @description: Generate temporary URL for file download/preview
|
|
20
|
+
* @param {DownloadConfig} downloadConfig
|
|
21
|
+
* @return Promise<any>
|
|
22
|
+
*/
|
|
23
|
+
static download(downloadConfig) {
|
|
24
|
+
const { url, method, headers, body, option } = downloadConfig;
|
|
25
|
+
let tempBody = body;
|
|
26
|
+
try {
|
|
27
|
+
if (tempBody && tempBody instanceof FormData && option) {
|
|
28
|
+
tempBody.append("options", JSON.stringify(option));
|
|
29
|
+
console.warn("Since body is FormData type, option field (image processing parameters) may become ineffective");
|
|
30
|
+
} else if (tempBody && isJson(tempBody)) {
|
|
31
|
+
tempBody = JSON.stringify({
|
|
32
|
+
...JSON.parse(tempBody),
|
|
33
|
+
options: option
|
|
34
|
+
});
|
|
35
|
+
} else if (tempBody && isObject(tempBody)) {
|
|
36
|
+
tempBody = JSON.stringify({
|
|
37
|
+
...tempBody,
|
|
38
|
+
options: option
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
} catch (e) {
|
|
42
|
+
tempBody = body;
|
|
43
|
+
}
|
|
44
|
+
return request({
|
|
45
|
+
url,
|
|
46
|
+
method: method || "post",
|
|
47
|
+
headers,
|
|
48
|
+
data: tempBody,
|
|
49
|
+
success: (response) => {
|
|
50
|
+
logPubSub.report({
|
|
51
|
+
type: "SUCCESS",
|
|
52
|
+
eventName: "download",
|
|
53
|
+
eventParams: {
|
|
54
|
+
url,
|
|
55
|
+
method: method || "post",
|
|
56
|
+
headers,
|
|
57
|
+
body: tempBody
|
|
58
|
+
},
|
|
59
|
+
eventResponse: response
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
fail: (status, reject) => {
|
|
63
|
+
const error = new DownloadException(
|
|
64
|
+
DownloadExceptionCode.DOWNLOAD_REQUEST_ERROR,
|
|
65
|
+
status
|
|
66
|
+
);
|
|
67
|
+
reject(error);
|
|
68
|
+
logPubSub.report({
|
|
69
|
+
type: "ERROR",
|
|
70
|
+
eventName: "download",
|
|
71
|
+
eventParams: {
|
|
72
|
+
url,
|
|
73
|
+
method: method || "post",
|
|
74
|
+
headers,
|
|
75
|
+
body: tempBody
|
|
76
|
+
},
|
|
77
|
+
error
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* @description: File upload interface, including simple upload/multipart upload/resumable upload, will select the corresponding platform and upload method based on upload credential information
|
|
84
|
+
* @param {UploadConfig} uploadConfig Upload configuration
|
|
85
|
+
* @return {UploadCallBack} uploadCallBack Upload callback
|
|
86
|
+
*/
|
|
87
|
+
upload(uploadConfig) {
|
|
88
|
+
const { url, method, file, option, customCredentials } = uploadConfig;
|
|
89
|
+
if (!customCredentials && (!url || !method)) {
|
|
90
|
+
throw new InitException(InitExceptionCode.MISSING_PARAMS_FOR_UPLOAD, "url", "method");
|
|
91
|
+
}
|
|
92
|
+
if (customCredentials) {
|
|
93
|
+
const { platform, temporary_credential } = customCredentials;
|
|
94
|
+
if (!platform || !temporary_credential) {
|
|
95
|
+
throw new InitException(
|
|
96
|
+
InitExceptionCode.MISSING_PARAMS_FOR_UPLOAD,
|
|
97
|
+
"platform",
|
|
98
|
+
"credentials"
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const { rewriteFileName } = option || {};
|
|
103
|
+
if (rewriteFileName) {
|
|
104
|
+
const suffix = getFileExtension(uploadConfig.fileName);
|
|
105
|
+
uploadConfig.fileName = `${nanoid()}.${suffix}`;
|
|
106
|
+
}
|
|
107
|
+
const hasError = checkSpecialCharacters(uploadConfig.fileName);
|
|
108
|
+
if (hasError) {
|
|
109
|
+
throw new InitException(
|
|
110
|
+
InitExceptionCode.UPLOAD_FILENAME_EXIST_SPECIAL_CHAR,
|
|
111
|
+
uploadConfig.fileName
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
return this.uploadManger.createTask(file, uploadConfig.fileName, uploadConfig, option || {});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* @description: Pause all file uploads (multipart upload)
|
|
118
|
+
*/
|
|
119
|
+
pause() {
|
|
120
|
+
this.uploadManger.pauseAllTask();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* @description: Resume all file uploads (multipart upload)
|
|
124
|
+
*/
|
|
125
|
+
resume() {
|
|
126
|
+
this.uploadManger.resumeAllTask();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* @description: Cancel all file uploads (multipart upload)
|
|
130
|
+
*/
|
|
131
|
+
cancel() {
|
|
132
|
+
this.uploadManger.cancelAllTask();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* @description: Pass in callback function to subscribe to log content
|
|
136
|
+
*/
|
|
137
|
+
static subscribeLogs(callback) {
|
|
138
|
+
logPubSub.subscribe(callback);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
__name(_Upload, "Upload");
|
|
142
|
+
/** Package version */
|
|
143
|
+
_Upload.version = version;
|
|
144
|
+
let Upload = _Upload;
|
|
145
|
+
import { default as default2 } from "./modules/TOS";
|
|
146
|
+
import { default as default3 } from "./modules/OSS";
|
|
147
|
+
import { default as default4 } from "./modules/OBS";
|
|
148
|
+
import { default as default5 } from "./modules/Kodo";
|
|
149
|
+
import { default as default6 } from "./modules/Local";
|
|
150
|
+
import { default as default7 } from "./modules/MinIO";
|
|
151
|
+
export {
|
|
152
|
+
default5 as Kodo,
|
|
153
|
+
default6 as Local,
|
|
154
|
+
default7 as MinIO,
|
|
155
|
+
default4 as OBS,
|
|
156
|
+
default3 as OSS,
|
|
157
|
+
PlatformModules,
|
|
158
|
+
PlatformType,
|
|
159
|
+
default2 as TOS,
|
|
160
|
+
Upload
|
|
161
|
+
};
|
|
162
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["import { version } from \"../package.json\"\nimport { DownloadException, DownloadExceptionCode } from \"./Exception/DownloadException\"\nimport { InitException, InitExceptionCode } from \"./Exception/InitException\"\nimport PlatformModules from \"./modules\"\nimport type { DownloadConfig, UploadCallBack, UploadConfig } from \"./types\"\nimport { PlatformType } from \"./types\"\nimport type { LogModule } from \"./types/log\"\nimport { isJson, isObject } from \"./utils/checkDataFormat\"\nimport logPubSub from \"./utils/logPubSub\"\nimport { request } from \"./utils/request\"\nimport { UploadManger } from \"./utils/UploadManger\"\nimport { checkSpecialCharacters, getFileExtension } from \"./utils\"\nimport { nanoid } from \"./utils/nanoid\"\n\nexport class Upload {\n\t/** Package version */\n\tstatic version: string = version\n\n\tuploadManger: UploadManger\n\n\tpublic constructor() {\n\t\tthis.uploadManger = new UploadManger()\n\t}\n\n\t/**\n\t * @description: Generate temporary URL for file download/preview\n\t * @param {DownloadConfig} downloadConfig\n\t * @return Promise<any>\n\t */\n\tpublic static download(downloadConfig: DownloadConfig): Promise<any> {\n\t\tconst { url, method, headers, body, option } = downloadConfig\n\t\tlet tempBody = body\n\n\t\ttry {\n\t\t\t// If body is FormData format\n\t\t\tif (tempBody && tempBody instanceof FormData && option) {\n\t\t\t\ttempBody.append(\"options\", JSON.stringify(option))\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(\"Since body is FormData type, option field (image processing parameters) may become ineffective\")\n\t\t\t} else if (tempBody && isJson(tempBody)) {\n\t\t\t\t// If body is JSON format\n\t\t\t\ttempBody = JSON.stringify({\n\t\t\t\t\t...JSON.parse(tempBody),\n\t\t\t\t\toptions: option,\n\t\t\t\t})\n\t\t\t} else if (tempBody && isObject(tempBody)) {\n\t\t\t\t// If body is Object format\n\t\t\t\ttempBody = JSON.stringify({\n\t\t\t\t\t...tempBody,\n\t\t\t\t\toptions: option,\n\t\t\t\t})\n\t\t\t}\n\t\t} catch (e) {\n\t\t\ttempBody = body\n\t\t}\n\n\t\treturn request({\n\t\t\turl,\n\t\t\tmethod: method || \"post\",\n\t\t\theaders,\n\t\t\tdata: tempBody,\n\t\t\tsuccess: (response) => {\n\t\t\t\tlogPubSub.report({\n\t\t\t\t\ttype: \"SUCCESS\",\n\t\t\t\t\teventName: \"download\",\n\t\t\t\t\teventParams: {\n\t\t\t\t\t\turl,\n\t\t\t\t\t\tmethod: method || \"post\",\n\t\t\t\t\t\theaders,\n\t\t\t\t\t\tbody: tempBody,\n\t\t\t\t\t},\n\t\t\t\t\teventResponse: response,\n\t\t\t\t})\n\t\t\t},\n\t\t\tfail: (status, reject) => {\n\t\t\t\tconst error = new DownloadException(\n\t\t\t\t\tDownloadExceptionCode.DOWNLOAD_REQUEST_ERROR,\n\t\t\t\t\tstatus,\n\t\t\t\t)\n\t\t\t\treject(error)\n\t\t\t\tlogPubSub.report({\n\t\t\t\t\ttype: \"ERROR\",\n\t\t\t\t\teventName: \"download\",\n\t\t\t\t\teventParams: {\n\t\t\t\t\t\turl,\n\t\t\t\t\t\tmethod: method || \"post\",\n\t\t\t\t\t\theaders,\n\t\t\t\t\t\tbody: tempBody,\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t})\n\t\t\t},\n\t\t})\n\t}\n\n\t/**\n\t * @description: File upload interface, including simple upload/multipart upload/resumable upload, will select the corresponding platform and upload method based on upload credential information\n\t * @param {UploadConfig} uploadConfig Upload configuration\n\t * @return {UploadCallBack} uploadCallBack Upload callback\n\t */\n\tpublic upload(uploadConfig: UploadConfig): UploadCallBack {\n\t\tconst { url, method, file, option, customCredentials } = uploadConfig\n\n\t\t// Validate parameters: if no custom credentials provided, url and method must be provided\n\t\tif (!customCredentials && (!url || !method)) {\n\t\t\tthrow new InitException(InitExceptionCode.MISSING_PARAMS_FOR_UPLOAD, \"url\", \"method\")\n\t\t}\n\n\t\t// If custom credentials are provided, validate credential parameters\n\t\tif (customCredentials) {\n\t\t\tconst { platform, temporary_credential } = customCredentials\n\t\t\tif (!platform || !temporary_credential) {\n\t\t\t\tthrow new InitException(\n\t\t\t\t\tInitExceptionCode.MISSING_PARAMS_FOR_UPLOAD,\n\t\t\t\t\t\"platform\",\n\t\t\t\t\t\"credentials\",\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\t// Handle filename\n\t\tconst { rewriteFileName } = option || {}\n\t\tif (rewriteFileName) {\n\t\t\tconst suffix = getFileExtension(uploadConfig.fileName)\n\t\t\tuploadConfig.fileName = `${nanoid()}.${suffix}`\n\t\t}\n\n\t\t// Check if filename contains special characters\n\t\tconst hasError = checkSpecialCharacters(uploadConfig.fileName)\n\t\tif (hasError) {\n\t\t\tthrow new InitException(\n\t\t\t\tInitExceptionCode.UPLOAD_FILENAME_EXIST_SPECIAL_CHAR,\n\t\t\t\tuploadConfig.fileName,\n\t\t\t)\n\t\t}\n\t\treturn this.uploadManger.createTask(file, uploadConfig.fileName, uploadConfig, option || {})\n\t}\n\n\t/**\n\t * @description: Pause all file uploads (multipart upload)\n\t */\n\tpublic pause() {\n\t\tthis.uploadManger.pauseAllTask()\n\t}\n\n\t/**\n\t * @description: Resume all file uploads (multipart upload)\n\t */\n\tpublic resume() {\n\t\tthis.uploadManger.resumeAllTask()\n\t}\n\n\t/**\n\t * @description: Cancel all file uploads (multipart upload)\n\t */\n\tpublic cancel() {\n\t\tthis.uploadManger.cancelAllTask()\n\t}\n\n\t/**\n\t * @description: Pass in callback function to subscribe to log content\n\t */\n\tstatic subscribeLogs(callback: LogModule.CallBack) {\n\t\tlogPubSub.subscribe(callback)\n\t}\n}\n\n// Export types and functions\nexport type { DownloadConfig, UploadCallBack, UploadConfig }\nexport { PlatformType, PlatformModules }\n\nexport { default as TOS } from \"./modules/TOS\"\nexport { default as OSS } from \"./modules/OSS\"\nexport { default as OBS } from \"./modules/OBS\"\nexport { default as Kodo } from \"./modules/Kodo\"\nexport { default as Local } from \"./modules/Local\"\nexport { default as MinIO } from \"./modules/MinIO\"\n\n\n\n\n"],"mappings":"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","names":["default"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { InitException, InitExceptionCode } from "../../Exception/InitException";
|
|
4
|
+
import { UploadException, UploadExceptionCode } from "../../Exception/UploadException";
|
|
5
|
+
import { request } from "../../utils/request";
|
|
6
|
+
const defaultUpload = /* @__PURE__ */ __name((file, key, params, option) => {
|
|
7
|
+
const { token, dir } = params;
|
|
8
|
+
if (!token || !dir) {
|
|
9
|
+
throw new InitException(
|
|
10
|
+
InitExceptionCode.MISSING_CREDENTIALS_PARAMS_FOR_UPLOAD,
|
|
11
|
+
"qiniu",
|
|
12
|
+
"token",
|
|
13
|
+
"dir"
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
const formData = new FormData();
|
|
17
|
+
formData.append("key", `${dir}${key}`);
|
|
18
|
+
formData.append("token", token);
|
|
19
|
+
formData.append("file", file);
|
|
20
|
+
return request({
|
|
21
|
+
method: "post",
|
|
22
|
+
url: "https://upload.qiniup.com",
|
|
23
|
+
data: formData,
|
|
24
|
+
headers: option?.headers ? option?.headers : {},
|
|
25
|
+
taskId: option.taskId,
|
|
26
|
+
onProgress: option?.progress ? option.progress : () => {
|
|
27
|
+
},
|
|
28
|
+
fail: (status, reject) => {
|
|
29
|
+
if (status === 401) {
|
|
30
|
+
reject(new UploadException(UploadExceptionCode.UPLOAD_CREDENTIALS_IS_EXPIRED));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}, "defaultUpload");
|
|
35
|
+
export {
|
|
36
|
+
defaultUpload
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=defaultUpload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/Kodo/defaultUpload.ts"],"sourcesContent":["import { InitException, InitExceptionCode } from \"../../Exception/InitException\"\nimport { UploadException, UploadExceptionCode } from \"../../Exception/UploadException\"\nimport type { PlatformRequest, PlatformSimpleUploadOption } from \"../../types\"\nimport type { Kodo } from \"../../types/Kodo\"\nimport { request } from \"../../utils/request\"\n\n/**\n * @description: Simple upload POST request\n * @param {File | Blob} file File\n * @param {String} key File name\n * @param {Kodo.AuthParams} params Upload credential info\n * @param {PlatformSimpleUploadOption} option Configuration field\n */\nexport const defaultUpload: PlatformRequest<Kodo.AuthParams, PlatformSimpleUploadOption> = (\n\tfile,\n\tkey,\n\tparams,\n\toption,\n) => {\n\tconst { token, dir } = params\n\n\tif (!token || !dir) {\n\t\tthrow new InitException(\n\t\t\tInitExceptionCode.MISSING_CREDENTIALS_PARAMS_FOR_UPLOAD,\n\t\t\t\"qiniu\",\n\t\t\t\"token\",\n\t\t\t\"dir\",\n\t\t)\n\t}\n\n\t// Wrap the FormData object\n\tconst formData = new FormData()\n\tformData.append(\"key\", `${dir}${key}`)\n\tformData.append(\"token\", token)\n\tformData.append(\"file\", file)\n\n\t// Send request\n\treturn request({\n\t\tmethod: \"post\",\n\t\turl: \"https://upload.qiniup.com\",\n\t\tdata: formData,\n\t\theaders: option?.headers ? option?.headers : {},\n\t\ttaskId: option.taskId,\n\t\tonProgress: option?.progress ? option.progress : () => {},\n\t\tfail: (status, reject) => {\n\t\t\tif (status === 401) {\n\t\t\t\treject(new UploadException(UploadExceptionCode.UPLOAD_CREDENTIALS_IS_EXPIRED))\n\t\t\t}\n\t\t},\n\t})\n}\n\n\n\n\n"],"mappings":";;AAAC,SAAS,eAAe,yBAAyB;AAClD,SAAS,iBAAiB,2BAA2B;AAGrD,SAAS,eAAe;AASjB,MAAM,gBAA8E,wBAC1F,MACA,KACA,QACA,WACI;AACJ,QAAM,EAAE,OAAO,IAAI,IAAI;AAEvB,MAAI,CAAC,SAAS,CAAC,KAAK;AACnB,UAAM,IAAI;AAAA,MACT,kBAAkB;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAGA,QAAM,WAAW,IAAI,SAAS;AAC9B,WAAS,OAAO,OAAO,GAAG,GAAG,GAAG,GAAG,EAAE;AACrC,WAAS,OAAO,SAAS,KAAK;AAC9B,WAAS,OAAO,QAAQ,IAAI;AAG5B,SAAO,QAAQ;AAAA,IACd,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,MAAM;AAAA,IACN,SAAS,QAAQ,UAAU,QAAQ,UAAU,CAAC;AAAA,IAC9C,QAAQ,OAAO;AAAA,IACf,YAAY,QAAQ,WAAW,OAAO,WAAW,MAAM;AAAA,IAAC;AAAA,IACxD,MAAM,CAAC,QAAQ,WAAW;AACzB,UAAI,WAAW,KAAK;AACnB,eAAO,IAAI,gBAAgB,oBAAoB,6BAA6B,CAAC;AAAA,MAC9E;AAAA,IACD;AAAA,EACD,CAAC;AACF,GArC2F;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/Kodo/index.ts"],"sourcesContent":["import { defaultUpload } from \"./defaultUpload\"\n\nexport default {\n\tupload: defaultUpload,\n}\n\n\n\n\n"],"mappings":"AAAC,SAAS,qBAAqB;AAE/B,IAAO,eAAQ;AAAA,EACd,QAAQ;AACT;","names":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { request } from "../../utils/request";
|
|
4
|
+
import { PlatformType } from "../../types";
|
|
5
|
+
import { UploadException, UploadExceptionCode } from "../../Exception/UploadException";
|
|
6
|
+
import { normalizeSuccessResponse } from "../../utils/response";
|
|
7
|
+
const upload = /* @__PURE__ */ __name(async (file, key, params, options) => {
|
|
8
|
+
const combinedKey = `${params.dir}${key}`;
|
|
9
|
+
const formData = new FormData();
|
|
10
|
+
formData.append("key", combinedKey);
|
|
11
|
+
formData.append("file", file);
|
|
12
|
+
formData.append("credential", params.credential);
|
|
13
|
+
return request({
|
|
14
|
+
method: "post",
|
|
15
|
+
url: params.host,
|
|
16
|
+
data: formData,
|
|
17
|
+
taskId: options.taskId,
|
|
18
|
+
fail: (status, reject) => {
|
|
19
|
+
if (status === 403) {
|
|
20
|
+
reject(new UploadException(UploadExceptionCode.UPLOAD_CREDENTIALS_IS_EXPIRED));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}).then(() => {
|
|
24
|
+
return normalizeSuccessResponse(combinedKey, PlatformType.Local, {});
|
|
25
|
+
});
|
|
26
|
+
}, "upload");
|
|
27
|
+
var Local_default = { upload };
|
|
28
|
+
export {
|
|
29
|
+
Local_default as default
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/Local/index.ts"],"sourcesContent":["import { request } from \"../../utils/request\"\nimport { PlatformRequest, PlatformSimpleUploadOption, PlatformType } from \"../../types\"\nimport { Local } from \"../../types/Local\"\nimport { UploadException, UploadExceptionCode } from \"../../Exception/UploadException\"\nimport { normalizeSuccessResponse } from \"../../utils/response\"\n\nconst upload: PlatformRequest<Local.AuthParams, PlatformSimpleUploadOption> = async (\n\tfile,\n\tkey,\n\tparams,\n\toptions,\n) => {\n\tconst combinedKey = `${params.dir}${key}`\n\n\tconst formData = new FormData()\n\tformData.append(\"key\", combinedKey)\n\tformData.append(\"file\", file)\n\tformData.append(\"credential\", params.credential)\n\n\treturn request({\n\t\tmethod: \"post\",\n\t\turl: params.host,\n\t\tdata: formData,\n\t\ttaskId: options.taskId,\n\t\tfail: (status, reject) => {\n\t\t\tif (status === 403) {\n\t\t\t\treject(new UploadException(UploadExceptionCode.UPLOAD_CREDENTIALS_IS_EXPIRED))\n\t\t\t}\n\t\t},\n\t}).then(() => {\n\t\treturn normalizeSuccessResponse(combinedKey, PlatformType.Local, {})\n\t})\n}\n\nexport default { upload }\n\n\n\n\n"],"mappings":";;AAAC,SAAS,eAAe;AACzB,SAAsD,oBAAoB;AAE1E,SAAS,iBAAiB,2BAA2B;AACrD,SAAS,gCAAgC;AAEzC,MAAM,SAAwE,8BAC7E,MACA,KACA,QACA,YACI;AACJ,QAAM,cAAc,GAAG,OAAO,GAAG,GAAG,GAAG;AAEvC,QAAM,WAAW,IAAI,SAAS;AAC9B,WAAS,OAAO,OAAO,WAAW;AAClC,WAAS,OAAO,QAAQ,IAAI;AAC5B,WAAS,OAAO,cAAc,OAAO,UAAU;AAE/C,SAAO,QAAQ;AAAA,IACd,QAAQ;AAAA,IACR,KAAK,OAAO;AAAA,IACZ,MAAM;AAAA,IACN,QAAQ,QAAQ;AAAA,IAChB,MAAM,CAAC,QAAQ,WAAW;AACzB,UAAI,WAAW,KAAK;AACnB,eAAO,IAAI,gBAAgB,oBAAoB,6BAA6B,CAAC;AAAA,MAC9E;AAAA,IACD;AAAA,EACD,CAAC,EAAE,KAAK,MAAM;AACb,WAAO,yBAAyB,aAAa,aAAa,OAAO,CAAC,CAAC;AAAA,EACpE,CAAC;AACF,GA1B8E;AA4B9E,IAAO,gBAAQ,EAAE,OAAO;","names":[]}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import {
|
|
4
|
+
CompleteMultipartUploadCommand,
|
|
5
|
+
CreateMultipartUploadCommand,
|
|
6
|
+
S3Client,
|
|
7
|
+
UploadPartCommand
|
|
8
|
+
} from "@aws-sdk/client-s3";
|
|
9
|
+
import mime from "mime";
|
|
10
|
+
import { InitException, InitExceptionCode } from "../../Exception/InitException";
|
|
11
|
+
import { UploadException, UploadExceptionCode } from "../../Exception/UploadException";
|
|
12
|
+
import { PlatformType } from "../../types";
|
|
13
|
+
import { isBlob, isFile } from "../../utils/checkDataFormat";
|
|
14
|
+
import {
|
|
15
|
+
createBuffer,
|
|
16
|
+
divideParts,
|
|
17
|
+
getPartSize,
|
|
18
|
+
initCheckpoint,
|
|
19
|
+
parallelSend
|
|
20
|
+
} from "../../utils/multipart";
|
|
21
|
+
import { parseExtname } from "../../utils/regExpUtil";
|
|
22
|
+
import { createAbortSignal, getTaskAbortState } from "../../utils/request";
|
|
23
|
+
import { normalizeSuccessResponse } from "../../utils/response";
|
|
24
|
+
import { STSUpload } from "./STSUpload";
|
|
25
|
+
const S3_MIN_PART_SIZE = 5 * 1024 * 1024;
|
|
26
|
+
const UPLOAD_STATUS_CODE = {
|
|
27
|
+
CANCEL: 5001,
|
|
28
|
+
PAUSE: 5002
|
|
29
|
+
};
|
|
30
|
+
function createAbortError(taskId, message) {
|
|
31
|
+
const abortError = new Error(message);
|
|
32
|
+
if (taskId) {
|
|
33
|
+
const abortState = getTaskAbortState(taskId);
|
|
34
|
+
abortError.status = abortState === "pause" ? UPLOAD_STATUS_CODE.PAUSE : UPLOAD_STATUS_CODE.CANCEL;
|
|
35
|
+
} else {
|
|
36
|
+
abortError.status = UPLOAD_STATUS_CODE.CANCEL;
|
|
37
|
+
}
|
|
38
|
+
return abortError;
|
|
39
|
+
}
|
|
40
|
+
__name(createAbortError, "createAbortError");
|
|
41
|
+
function createS3Client(params) {
|
|
42
|
+
const { endpoint, region, credentials } = params;
|
|
43
|
+
const { access_key_id, secret_access_key, session_token } = credentials;
|
|
44
|
+
return new S3Client({
|
|
45
|
+
region,
|
|
46
|
+
endpoint,
|
|
47
|
+
credentials: {
|
|
48
|
+
accessKeyId: access_key_id,
|
|
49
|
+
secretAccessKey: secret_access_key,
|
|
50
|
+
sessionToken: session_token
|
|
51
|
+
},
|
|
52
|
+
// Force path-style for MinIO compatibility
|
|
53
|
+
forcePathStyle: true
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
__name(createS3Client, "createS3Client");
|
|
57
|
+
async function initMultipartUpload(name, params, option, abortSignal, taskId) {
|
|
58
|
+
const { bucket } = params;
|
|
59
|
+
const s3Client = createS3Client(params);
|
|
60
|
+
const command = new CreateMultipartUploadCommand({
|
|
61
|
+
Bucket: bucket,
|
|
62
|
+
Key: name,
|
|
63
|
+
ContentType: option.mime || void 0
|
|
64
|
+
});
|
|
65
|
+
try {
|
|
66
|
+
const response = await s3Client.send(command, abortSignal ? { abortSignal } : {});
|
|
67
|
+
return {
|
|
68
|
+
bucket: response.Bucket || bucket,
|
|
69
|
+
name: response.Key || name,
|
|
70
|
+
UploadId: response.UploadId || ""
|
|
71
|
+
};
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (error.name === "AbortError" || error.name === "CanceledError") {
|
|
74
|
+
throw createAbortError(taskId, "Upload initialization aborted");
|
|
75
|
+
}
|
|
76
|
+
if (error.name === "InvalidAccessKeyId" || error.name === "SignatureDoesNotMatch" || error.$metadata?.httpStatusCode === 403) {
|
|
77
|
+
throw new UploadException(
|
|
78
|
+
UploadExceptionCode.UPLOAD_CREDENTIALS_IS_EXPIRED,
|
|
79
|
+
"Failed to initialize multipart upload: Invalid credentials"
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
__name(initMultipartUpload, "initMultipartUpload");
|
|
86
|
+
async function completeMultipartUpload(name, UploadId, parts, params, options, fileSize, abortSignal, taskId) {
|
|
87
|
+
const { bucket } = params;
|
|
88
|
+
const s3Client = createS3Client(params);
|
|
89
|
+
const sortedParts = parts.concat().sort((a, b) => a.number - b.number).filter((item, index, arr) => {
|
|
90
|
+
const prevItem = arr[index - 1];
|
|
91
|
+
return !index || prevItem && item.number !== prevItem.number;
|
|
92
|
+
});
|
|
93
|
+
const command = new CompleteMultipartUploadCommand({
|
|
94
|
+
Bucket: bucket,
|
|
95
|
+
Key: name,
|
|
96
|
+
UploadId,
|
|
97
|
+
MultipartUpload: {
|
|
98
|
+
Parts: sortedParts.map((part) => ({
|
|
99
|
+
PartNumber: part.number,
|
|
100
|
+
ETag: part.etag
|
|
101
|
+
}))
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
try {
|
|
105
|
+
const response = await s3Client.send(command, abortSignal ? { abortSignal } : {});
|
|
106
|
+
if (options.progress) {
|
|
107
|
+
options.progress(100, fileSize, fileSize, null);
|
|
108
|
+
}
|
|
109
|
+
return normalizeSuccessResponse(name, PlatformType.Minio, {
|
|
110
|
+
etag: response.ETag || "",
|
|
111
|
+
location: response.Location || ""
|
|
112
|
+
});
|
|
113
|
+
} catch (error) {
|
|
114
|
+
if (error.name === "AbortError" || error.name === "CanceledError") {
|
|
115
|
+
throw createAbortError(taskId, "Upload completion aborted");
|
|
116
|
+
}
|
|
117
|
+
if (error.name === "InvalidAccessKeyId" || error.name === "SignatureDoesNotMatch" || error.$metadata?.httpStatusCode === 403) {
|
|
118
|
+
throw new UploadException(
|
|
119
|
+
UploadExceptionCode.UPLOAD_CREDENTIALS_IS_EXPIRED,
|
|
120
|
+
"Failed to complete multipart upload: Invalid credentials"
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
__name(completeMultipartUpload, "completeMultipartUpload");
|
|
127
|
+
async function uploadPart(name, UploadId, partNo, data, params, abortSignal, taskId) {
|
|
128
|
+
const { bucket } = params;
|
|
129
|
+
const s3Client = createS3Client(params);
|
|
130
|
+
let bodyData;
|
|
131
|
+
if (data.content instanceof ArrayBuffer) {
|
|
132
|
+
bodyData = new Uint8Array(data.content);
|
|
133
|
+
} else if (data.content instanceof Blob) {
|
|
134
|
+
const arrayBuffer = await data.content.arrayBuffer();
|
|
135
|
+
bodyData = new Uint8Array(arrayBuffer);
|
|
136
|
+
} else {
|
|
137
|
+
bodyData = data.content;
|
|
138
|
+
}
|
|
139
|
+
const command = new UploadPartCommand({
|
|
140
|
+
Bucket: bucket,
|
|
141
|
+
Key: name,
|
|
142
|
+
UploadId,
|
|
143
|
+
PartNumber: partNo,
|
|
144
|
+
Body: bodyData
|
|
145
|
+
});
|
|
146
|
+
try {
|
|
147
|
+
const response = await s3Client.send(command, abortSignal ? { abortSignal } : {});
|
|
148
|
+
if (!response.ETag) {
|
|
149
|
+
throw new InitException(InitExceptionCode.UPLOAD_HEAD_NO_EXPOSE_ETAG);
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
name,
|
|
153
|
+
etag: response.ETag,
|
|
154
|
+
res: response
|
|
155
|
+
};
|
|
156
|
+
} catch (error) {
|
|
157
|
+
if (error.name === "AbortError" || error.name === "CanceledError") {
|
|
158
|
+
throw createAbortError(taskId, "Upload part aborted");
|
|
159
|
+
}
|
|
160
|
+
if (error.name === "InvalidAccessKeyId" || error.name === "SignatureDoesNotMatch" || error.$metadata?.httpStatusCode === 403) {
|
|
161
|
+
const errorDetails = [
|
|
162
|
+
"MinIO/S3 multipart upload authentication failed.",
|
|
163
|
+
"Possible causes:",
|
|
164
|
+
"1. Access Key ID or Secret Access Key is incorrect",
|
|
165
|
+
"2. Region or endpoint configuration mismatch",
|
|
166
|
+
"3. System time difference exceeds 15 minutes",
|
|
167
|
+
"4. Credentials do not have permission to upload to this bucket/path",
|
|
168
|
+
"5. Session token has expired (for temporary credentials)"
|
|
169
|
+
].join(" ");
|
|
170
|
+
throw new UploadException(
|
|
171
|
+
UploadExceptionCode.UPLOAD_CREDENTIALS_IS_EXPIRED,
|
|
172
|
+
errorDetails
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
__name(uploadPart, "uploadPart");
|
|
179
|
+
async function resumeMultipart(checkpoint, params, options) {
|
|
180
|
+
const taskId = options.taskId;
|
|
181
|
+
const { file, fileSize, partSize, UploadId, doneParts, name } = checkpoint;
|
|
182
|
+
const internalDoneParts = doneParts.length > 0 ? [...doneParts] : [];
|
|
183
|
+
const partOffs = divideParts(fileSize, partSize);
|
|
184
|
+
const numParts = partOffs.length;
|
|
185
|
+
let multipartFinish = false;
|
|
186
|
+
const opt = { ...options, partSize };
|
|
187
|
+
const uploadPartJob = /* @__PURE__ */ __name((partNo) => (
|
|
188
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
189
|
+
new Promise(async (resolve, reject) => {
|
|
190
|
+
try {
|
|
191
|
+
const pi = partOffs[partNo - 1];
|
|
192
|
+
if (!pi) {
|
|
193
|
+
reject(new Error(`Part ${partNo} not found`));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const content = await createBuffer(file, pi.start, pi.end);
|
|
197
|
+
const data = {
|
|
198
|
+
content,
|
|
199
|
+
size: pi.end - pi.start
|
|
200
|
+
};
|
|
201
|
+
const abortSignal = taskId ? createAbortSignal(taskId) : void 0;
|
|
202
|
+
const result = await uploadPart(name, UploadId, partNo, data, params, abortSignal, taskId);
|
|
203
|
+
if (!multipartFinish) {
|
|
204
|
+
checkpoint.doneParts.push({
|
|
205
|
+
number: partNo,
|
|
206
|
+
etag: result.etag
|
|
207
|
+
});
|
|
208
|
+
if (typeof options.progress === "function") {
|
|
209
|
+
const completedParts = checkpoint.doneParts.length;
|
|
210
|
+
const progressPercent = completedParts / numParts * 100;
|
|
211
|
+
const uploadedSize = Math.min(completedParts * partSize, fileSize);
|
|
212
|
+
options.progress(
|
|
213
|
+
progressPercent,
|
|
214
|
+
uploadedSize,
|
|
215
|
+
fileSize,
|
|
216
|
+
checkpoint
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
resolve({
|
|
220
|
+
number: partNo,
|
|
221
|
+
etag: result.etag
|
|
222
|
+
});
|
|
223
|
+
} else {
|
|
224
|
+
resolve();
|
|
225
|
+
}
|
|
226
|
+
} catch (err) {
|
|
227
|
+
const tempErr = new Error();
|
|
228
|
+
tempErr.name = err.name;
|
|
229
|
+
tempErr.message = err.message;
|
|
230
|
+
tempErr.stack = err.stack;
|
|
231
|
+
tempErr.partNum = partNo;
|
|
232
|
+
tempErr.status = err.status;
|
|
233
|
+
reject(tempErr);
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
), "uploadPartJob");
|
|
237
|
+
const all = Array.from(new Array(numParts), (_, i) => i + 1);
|
|
238
|
+
const done = internalDoneParts.map((p) => p.number);
|
|
239
|
+
const todo = all.filter((p) => done.indexOf(p) < 0);
|
|
240
|
+
const defaultParallel = 5;
|
|
241
|
+
const parallel = opt.parallel || defaultParallel;
|
|
242
|
+
const jobErr = await parallelSend(
|
|
243
|
+
todo,
|
|
244
|
+
parallel,
|
|
245
|
+
(value) => new Promise((resolve, reject) => {
|
|
246
|
+
uploadPartJob(value).then((result) => {
|
|
247
|
+
if (result) {
|
|
248
|
+
internalDoneParts.push(result);
|
|
249
|
+
}
|
|
250
|
+
resolve();
|
|
251
|
+
}).catch((err) => {
|
|
252
|
+
reject(err);
|
|
253
|
+
});
|
|
254
|
+
})
|
|
255
|
+
);
|
|
256
|
+
multipartFinish = true;
|
|
257
|
+
if (jobErr && jobErr.length > 0) {
|
|
258
|
+
const error = jobErr[0];
|
|
259
|
+
if (!error) {
|
|
260
|
+
throw new UploadException(UploadExceptionCode.UPLOAD_MULTIPART_ERROR, "Unknown upload error");
|
|
261
|
+
}
|
|
262
|
+
if (error.status === UPLOAD_STATUS_CODE.CANCEL || error.status === UPLOAD_STATUS_CODE.PAUSE) {
|
|
263
|
+
throw error;
|
|
264
|
+
}
|
|
265
|
+
throw new UploadException(
|
|
266
|
+
UploadExceptionCode.UPLOAD_MULTIPART_ERROR,
|
|
267
|
+
error.message.replace("[Uploader] ", ""),
|
|
268
|
+
error.partNum
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
const completeAbortSignal = taskId ? createAbortSignal(taskId) : void 0;
|
|
272
|
+
return completeMultipartUpload(name, UploadId, internalDoneParts, params, opt, fileSize, completeAbortSignal, taskId);
|
|
273
|
+
}
|
|
274
|
+
__name(resumeMultipart, "resumeMultipart");
|
|
275
|
+
const MultipartUpload = /* @__PURE__ */ __name(async (file, key, params, option) => {
|
|
276
|
+
const options = { ...option };
|
|
277
|
+
const { region, bucket, dir, credentials, endpoint } = params;
|
|
278
|
+
if (!region || !bucket || !dir || !endpoint || !credentials || !credentials.access_key_id || !credentials.secret_access_key) {
|
|
279
|
+
throw new InitException(
|
|
280
|
+
InitExceptionCode.MISSING_CREDENTIALS_PARAMS_FOR_UPLOAD,
|
|
281
|
+
"s3",
|
|
282
|
+
"region",
|
|
283
|
+
"bucket",
|
|
284
|
+
"dir",
|
|
285
|
+
"endpoint",
|
|
286
|
+
"credentials.access_key_id",
|
|
287
|
+
"credentials.secret_access_key"
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
const name = `${dir}${key}`;
|
|
291
|
+
if (!options.mime) {
|
|
292
|
+
if (isFile(file)) {
|
|
293
|
+
options.mime = file.type;
|
|
294
|
+
} else if (isBlob(file)) {
|
|
295
|
+
options.mime = file.type;
|
|
296
|
+
} else {
|
|
297
|
+
options.mime = mime.getType(parseExtname(name));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (options.checkpoint && options.checkpoint.UploadId) {
|
|
301
|
+
if (file)
|
|
302
|
+
options.checkpoint.file = file;
|
|
303
|
+
return resumeMultipart(options.checkpoint, params, options);
|
|
304
|
+
}
|
|
305
|
+
options.headers = options.headers || {};
|
|
306
|
+
const fileSize = file.size;
|
|
307
|
+
if (fileSize < S3_MIN_PART_SIZE) {
|
|
308
|
+
return STSUpload(file, key, params, { ...options });
|
|
309
|
+
}
|
|
310
|
+
if (options.partSize && !(parseInt(String(options.partSize), 10) === options.partSize)) {
|
|
311
|
+
throw new InitException(InitExceptionCode.UPLOAD_API_OPTION_PARTSIZE_MUST_INT);
|
|
312
|
+
}
|
|
313
|
+
if (options.partSize && options.partSize < S3_MIN_PART_SIZE) {
|
|
314
|
+
throw new InitException(
|
|
315
|
+
InitExceptionCode.UPLOAD_API_OPTION_PARTSIZE_IS_SMALL,
|
|
316
|
+
S3_MIN_PART_SIZE
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
const taskId = options.taskId;
|
|
320
|
+
const initAbortSignal = taskId ? createAbortSignal(taskId) : void 0;
|
|
321
|
+
const { UploadId } = await initMultipartUpload(name, params, {
|
|
322
|
+
headers: { ...options.headers },
|
|
323
|
+
mime: options.mime
|
|
324
|
+
}, initAbortSignal, taskId);
|
|
325
|
+
const partSize = getPartSize(fileSize, options.partSize, S3_MIN_PART_SIZE);
|
|
326
|
+
const checkpoint = initCheckpoint(file, name, fileSize, partSize, UploadId);
|
|
327
|
+
if (options && options.progress) {
|
|
328
|
+
options.progress(0, 0, fileSize, checkpoint);
|
|
329
|
+
}
|
|
330
|
+
return resumeMultipart(checkpoint, params, options);
|
|
331
|
+
}, "MultipartUpload");
|
|
332
|
+
export {
|
|
333
|
+
MultipartUpload
|
|
334
|
+
};
|
|
335
|
+
//# sourceMappingURL=MultipartUpload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/MinIO/MultipartUpload.ts"],"sourcesContent":["import {\n\tCompleteMultipartUploadCommand,\n\tCreateMultipartUploadCommand,\n\tS3Client,\n\tUploadPartCommand,\n} from \"@aws-sdk/client-s3\"\nimport mime from \"mime\"\nimport { InitException, InitExceptionCode } from \"../../Exception/InitException\"\nimport { UploadException, UploadExceptionCode } from \"../../Exception/UploadException\"\nimport type { PlatformMultipartUploadOption, PlatformRequest } from \"../../types\"\nimport { PlatformType } from \"../../types\"\nimport type { ErrorType } from \"../../types/error\"\nimport type { MinIO } from \"../../types/MinIO\"\nimport { isBlob, isFile } from \"../../utils/checkDataFormat\"\nimport {\n\tcreateBuffer,\n\tdivideParts,\n\tgetPartSize,\n\tinitCheckpoint,\n\tparallelSend,\n} from \"../../utils/multipart\"\nimport { parseExtname } from \"../../utils/regExpUtil\"\nimport { createAbortSignal, getTaskAbortState } from \"../../utils/request\"\nimport { normalizeSuccessResponse } from \"../../utils/response\"\nimport { STSUpload } from \"./STSUpload\"\n\n// AWS S3 minimum part size is 5MB\nconst S3_MIN_PART_SIZE = 5 * 1024 * 1024\n\n// Upload abort status codes\nconst UPLOAD_STATUS_CODE = {\n\tCANCEL: 5001,\n\tPAUSE: 5002,\n} as const\n\n/**\n * Create an abort error with correct status code based on task abort state\n * @param {string} taskId Task ID\n * @param {string} message Error message\n * @returns Error with status property\n */\nfunction createAbortError(taskId: string | undefined, message: string): Error {\n\tconst abortError = new Error(message) as any\n\tif (taskId) {\n\t\tconst abortState = getTaskAbortState(taskId)\n\t\tabortError.status = abortState === \"pause\" ? UPLOAD_STATUS_CODE.PAUSE : UPLOAD_STATUS_CODE.CANCEL\n\t} else {\n\t\tabortError.status = UPLOAD_STATUS_CODE.CANCEL // Default to cancel\n\t}\n\treturn abortError\n}\n\n/**\n * Create S3Client instance with provided credentials\n */\nfunction createS3Client(params: MinIO.STSAuthParams): S3Client {\n\tconst { endpoint, region, credentials } = params\n\tconst { access_key_id, secret_access_key, session_token } = credentials\n\n\treturn new S3Client({\n\t\tregion,\n\t\tendpoint,\n\t\tcredentials: {\n\t\t\taccessKeyId: access_key_id,\n\t\t\tsecretAccessKey: secret_access_key,\n\t\t\tsessionToken: session_token,\n\t\t},\n\t\t// Force path-style for MinIO compatibility\n\t\tforcePathStyle: true,\n\t})\n}\n\n/**\n * @description: Initialize multipart upload to get UploadId from S3\n * @param {string} name Object key\n * @param {MinIO.STSAuthParams} params Credentials parameters\n * @param {MinIO.InitMultipartUploadOption} option Upload options\n * @param {AbortSignal} abortSignal Optional abort signal for cancellation\n * @param {string} taskId Optional task ID for error handling\n */\nasync function initMultipartUpload(\n\tname: string,\n\tparams: MinIO.STSAuthParams,\n\toption: MinIO.InitMultipartUploadOption,\n\tabortSignal?: AbortSignal,\n\ttaskId?: string,\n) {\n\tconst { bucket } = params\n\n\t// Create S3 client\n\tconst s3Client = createS3Client(params)\n\n\t// Create command\n\tconst command = new CreateMultipartUploadCommand({\n\t\tBucket: bucket,\n\t\tKey: name,\n\t\tContentType: option.mime || undefined,\n\t})\n\n\ttry {\n\t\tconst response = await s3Client.send(command, abortSignal ? { abortSignal } : {})\n\n\t\treturn {\n\t\t\tbucket: response.Bucket || bucket,\n\t\t\tname: response.Key || name,\n\t\t\tUploadId: response.UploadId || \"\",\n\t\t}\n\t} catch (error: any) {\n\t\t// Handle abort errors\n\t\tif (error.name === \"AbortError\" || error.name === \"CanceledError\") {\n\t\t\tthrow createAbortError(taskId, \"Upload initialization aborted\")\n\t\t}\n\t\t\n\t\tif (error.name === \"InvalidAccessKeyId\" || error.name === \"SignatureDoesNotMatch\" || error.$metadata?.httpStatusCode === 403) {\n\t\t\tthrow new UploadException(\n\t\t\t\tUploadExceptionCode.UPLOAD_CREDENTIALS_IS_EXPIRED,\n\t\t\t\t\"Failed to initialize multipart upload: Invalid credentials\",\n\t\t\t)\n\t\t}\n\t\tthrow error\n\t}\n}\n\n/**\n * @description: Complete multipart upload after all parts are uploaded\n * @param {String} name Object key\n * @param {String} UploadId Upload ID\n * @param {Array} parts Part information array\n * @param {MinIO.STSAuthParams} params Credentials parameters\n * @param {MinIO.CompleteMultipartUploadOptions} options Upload options\n * @param {number} fileSize Total file size\n * @param {AbortSignal} abortSignal Optional abort signal for cancellation\n * @param {string} taskId Optional task ID for error handling\n */\nasync function completeMultipartUpload(\n\tname: string,\n\tUploadId: string,\n\tparts: Array<{ number: number; etag: string }>,\n\tparams: MinIO.STSAuthParams,\n\toptions: MinIO.CompleteMultipartUploadOptions,\n\tfileSize: number,\n\tabortSignal?: AbortSignal,\n\ttaskId?: string,\n) {\n\tconst { bucket } = params\n\n\t// Create S3 client\n\tconst s3Client = createS3Client(params)\n\n\t// Sort parts by part number and remove duplicates\n\tconst sortedParts = parts\n\t\t.concat()\n\t\t.sort((a, b) => a.number - b.number)\n\t\t.filter((item, index, arr) => {\n\t\t\tconst prevItem = arr[index - 1]\n\t\t\treturn !index || (prevItem && item.number !== prevItem.number)\n\t\t})\n\n\t// Create command\n\tconst command = new CompleteMultipartUploadCommand({\n\t\tBucket: bucket,\n\t\tKey: name,\n\t\tUploadId: UploadId,\n\t\tMultipartUpload: {\n\t\t\tParts: sortedParts.map((part) => ({\n\t\t\t\tPartNumber: part.number,\n\t\t\t\tETag: part.etag,\n\t\t\t})),\n\t\t},\n\t})\n\n\ttry {\n\t\tconst response = await s3Client.send(command, abortSignal ? { abortSignal } : {})\n\n\t\t// Report 100% completion with actual file size\n\t\tif (options.progress) {\n\t\t\toptions.progress(100, fileSize, fileSize, null)\n\t\t}\n\n\t\treturn normalizeSuccessResponse(name, PlatformType.Minio, {\n\t\t\tetag: response.ETag || \"\",\n\t\t\tlocation: response.Location || \"\",\n\t\t})\n\t} catch (error: any) {\n\t\t// Handle abort errors\n\t\tif (error.name === \"AbortError\" || error.name === \"CanceledError\") {\n\t\t\tthrow createAbortError(taskId, \"Upload completion aborted\")\n\t\t}\n\t\t\n\t\tif (error.name === \"InvalidAccessKeyId\" || error.name === \"SignatureDoesNotMatch\" || error.$metadata?.httpStatusCode === 403) {\n\t\t\tthrow new UploadException(\n\t\t\t\tUploadExceptionCode.UPLOAD_CREDENTIALS_IS_EXPIRED,\n\t\t\t\t\"Failed to complete multipart upload: Invalid credentials\",\n\t\t\t)\n\t\t}\n\t\tthrow error\n\t}\n}\n\n/**\n * @description: Upload a single part\n * @param {String} name Object key\n * @param {String} UploadId Upload ID\n * @param {number} partNo Part number\n * @param {MinIO.PartInfo} data Part data\n * @param {MinIO.STSAuthParams} params Credentials parameters\n * @param {AbortSignal} abortSignal Optional abort signal for cancellation\n * @param {string} taskId Optional task ID for error handling\n */\nasync function uploadPart(\n\tname: string,\n\tUploadId: string,\n\tpartNo: number,\n\tdata: MinIO.PartInfo,\n\tparams: MinIO.STSAuthParams,\n\tabortSignal?: AbortSignal,\n\ttaskId?: string,\n) {\n\tconst { bucket } = params\n\n\t// Create S3 client\n\tconst s3Client = createS3Client(params)\n\n\t// Convert data.content to Uint8Array if needed\n\tlet bodyData: Uint8Array\n\tif (data.content instanceof ArrayBuffer) {\n\t\tbodyData = new Uint8Array(data.content)\n\t} else if (data.content instanceof Blob) {\n\t\tconst arrayBuffer = await data.content.arrayBuffer()\n\t\tbodyData = new Uint8Array(arrayBuffer)\n\t} else {\n\t\tbodyData = data.content as Uint8Array\n\t}\n\n\t// Create command\n\tconst command = new UploadPartCommand({\n\t\tBucket: bucket,\n\t\tKey: name,\n\t\tUploadId: UploadId,\n\t\tPartNumber: partNo,\n\t\tBody: bodyData,\n\t})\n\n\ttry {\n\t\t// Send command with optional abort signal\n\t\tconst response = await s3Client.send(command, abortSignal ? { abortSignal } : {})\n\n\t\tif (!response.ETag) {\n\t\t\tthrow new InitException(InitExceptionCode.UPLOAD_HEAD_NO_EXPOSE_ETAG)\n\t\t}\n\n\t\treturn {\n\t\t\tname,\n\t\t\tetag: response.ETag,\n\t\t\tres: response,\n\t\t}\n\t} catch (error: any) {\n\t\t// Handle abort errors\n\t\tif (error.name === \"AbortError\" || error.name === \"CanceledError\") {\n\t\t\tthrow createAbortError(taskId, \"Upload part aborted\")\n\t\t}\n\t\t\n\t\tif (error.name === \"InvalidAccessKeyId\" || error.name === \"SignatureDoesNotMatch\" || error.$metadata?.httpStatusCode === 403) {\n\t\t\tconst errorDetails = [\n\t\t\t\t\"MinIO/S3 multipart upload authentication failed.\",\n\t\t\t\t\"Possible causes:\",\n\t\t\t\t\"1. Access Key ID or Secret Access Key is incorrect\",\n\t\t\t\t\"2. Region or endpoint configuration mismatch\",\n\t\t\t\t\"3. System time difference exceeds 15 minutes\",\n\t\t\t\t\"4. Credentials do not have permission to upload to this bucket/path\",\n\t\t\t\t\"5. Session token has expired (for temporary credentials)\",\n\t\t\t].join(\" \")\n\t\t\t\n\t\t\tthrow new UploadException(\n\t\t\t\tUploadExceptionCode.UPLOAD_CREDENTIALS_IS_EXPIRED,\n\t\t\t\terrorDetails,\n\t\t\t)\n\t\t}\n\t\tthrow error\n\t}\n}\n\n/**\n * @description: Resume multipart upload or perform multipart upload\n * @param {Object} checkpoint Upload checkpoint information\n * @param {MinIO.STSAuthParams} params Credentials parameters\n * @param {MinIO.MultipartUploadOption} options Upload options\n */\nasync function resumeMultipart(\n\tcheckpoint: MinIO.Checkpoint,\n\tparams: MinIO.STSAuthParams,\n\toptions: MinIO.MultipartUploadOption,\n) {\n\tconst taskId = options.taskId\n\tconst { file, fileSize, partSize, UploadId, doneParts, name } = checkpoint\n\tconst internalDoneParts = doneParts.length > 0 ? [...doneParts] : []\n\tconst partOffs = divideParts(fileSize, partSize)\n\tconst numParts = partOffs.length\n\tlet multipartFinish = false\n\tconst opt = { ...options, partSize }\n\n\tconst uploadPartJob = (partNo: number): Promise<void | MinIO.DonePart> =>\n\t\t// eslint-disable-next-line no-async-promise-executor\n\t\tnew Promise(async (resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tconst pi = partOffs[partNo - 1]\n\t\t\t\tif (!pi) {\n\t\t\t\t\treject(new Error(`Part ${partNo} not found`))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst content = await createBuffer(file, pi.start, pi.end)\n\t\t\t\tconst data = {\n\t\t\t\t\tcontent,\n\t\t\t\t\tsize: pi.end - pi.start,\n\t\t\t\t}\n\n\t\t\t\t// Create abort signal for this upload part if taskId exists\n\t\t\t\tconst abortSignal = taskId ? createAbortSignal(taskId) : undefined\n\n\t\t\t\tconst result = await uploadPart(name, UploadId, partNo, data, params, abortSignal, taskId)\n\n\t\t\t\tif (!multipartFinish) {\n\t\t\t\t\tcheckpoint.doneParts.push({\n\t\t\t\t\t\tnumber: partNo,\n\t\t\t\t\t\tetag: result.etag,\n\t\t\t\t\t})\n\n\t\t\t\t\tif (typeof options.progress === \"function\") {\n\t\t\t\t\t\tconst completedParts = checkpoint.doneParts.length\n\t\t\t\t\t\tconst progressPercent = (completedParts / numParts) * 100\n\t\t\t\t\t\t// Calculate actual uploaded size considering last part may be smaller\n\t\t\t\t\t\tconst uploadedSize = Math.min(completedParts * partSize, fileSize)\n\t\t\t\t\t\toptions.progress(\n\t\t\t\t\t\t\tprogressPercent,\n\t\t\t\t\t\t\tuploadedSize,\n\t\t\t\t\t\t\tfileSize,\n\t\t\t\t\t\t\tcheckpoint,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve({\n\t\t\t\t\t\tnumber: partNo,\n\t\t\t\t\t\tetag: result.etag,\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tresolve()\n\t\t\t\t}\n\t\t\t} catch (err: any) {\n\t\t\t\tconst tempErr = new Error() as unknown as ErrorType.UploadPartException\n\t\t\t\ttempErr.name = err.name\n\t\t\t\ttempErr.message = err.message\n\t\t\t\ttempErr.stack = err.stack\n\t\t\t\ttempErr.partNum = partNo\n\t\t\t\ttempErr.status = err.status\n\n\t\t\t\treject(tempErr)\n\t\t\t}\n\t\t})\n\n\tconst all = Array.from(new Array(numParts), (_, i) => i + 1)\n\tconst done = internalDoneParts.map((p) => p.number)\n\tconst todo = all.filter((p) => done.indexOf(p) < 0)\n\tconst defaultParallel = 5\n\tconst parallel = opt.parallel || defaultParallel\n\n\t// Upload in parallel\n\tconst jobErr: ErrorType.UploadPartException[] = await parallelSend(\n\t\ttodo,\n\t\tparallel,\n\t\t(value) =>\n\t\t\tnew Promise((resolve, reject) => {\n\t\t\t\tuploadPartJob(value)\n\t\t\t\t\t.then((result: MinIO.DonePart | void) => {\n\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\tinternalDoneParts.push(result)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresolve()\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\treject(err)\n\t\t\t\t\t})\n\t\t\t}),\n\t)\n\n\tmultipartFinish = true\n\n\tif (jobErr && jobErr.length > 0) {\n\t\tconst error = jobErr[0]\n\t\tif (!error) {\n\t\t\tthrow new UploadException(UploadExceptionCode.UPLOAD_MULTIPART_ERROR, \"Unknown upload error\")\n\t\t}\n\t\t// Check if upload was cancelled or paused\n\t\tif (error.status === UPLOAD_STATUS_CODE.CANCEL || error.status === UPLOAD_STATUS_CODE.PAUSE) {\n\t\t\tthrow error as Error\n\t\t}\n\t\tthrow new UploadException(\n\t\t\tUploadExceptionCode.UPLOAD_MULTIPART_ERROR,\n\t\t\terror.message.replace(\"[Uploader] \", \"\"),\n\t\t\terror.partNum,\n\t\t)\n\t}\n\n\t// Create abort signal for completion if taskId exists\n\tconst completeAbortSignal = taskId ? createAbortSignal(taskId) : undefined\n\treturn completeMultipartUpload(name, UploadId, internalDoneParts, params, opt, fileSize, completeAbortSignal, taskId)\n}\n\n/**\n * @description: Multipart upload interface, supports resumable upload\n * @param {File | Blob} file File to upload\n * @param {String} key Object key\n * @param {MinIO.STSAuthParams} params Credentials parameters\n * @param {MinIO.MultipartUploadOption} option Upload options\n */\nexport const MultipartUpload: PlatformRequest<\n\tMinIO.STSAuthParams,\n\tPlatformMultipartUploadOption\n> = async (\n\tfile: File | Blob,\n\tkey: string,\n\tparams: MinIO.STSAuthParams,\n\toption: PlatformMultipartUploadOption,\n) => {\n\tconst options = { ...option }\n\tconst { region, bucket, dir, credentials, endpoint } = params\n\n\tif (!region || !bucket || !dir || !endpoint || !credentials || \n\t !credentials.access_key_id || !credentials.secret_access_key) {\n\t\tthrow new InitException(\n\t\t\tInitExceptionCode.MISSING_CREDENTIALS_PARAMS_FOR_UPLOAD,\n\t\t\t\"s3\",\n\t\t\t\"region\",\n\t\t\t\"bucket\",\n\t\t\t\"dir\",\n\t\t\t\"endpoint\",\n\t\t\t\"credentials.access_key_id\",\n\t\t\t\"credentials.secret_access_key\",\n\t\t)\n\t}\n\n\tconst name = `${dir}${key}`\n\n\t// Determine MIME type\n\tif (!options.mime) {\n\t\tif (isFile(file)) {\n\t\t\toptions.mime = file.type\n\t\t} else if (isBlob(file)) {\n\t\t\toptions.mime = file.type\n\t\t} else {\n\t\t\toptions.mime = mime.getType(parseExtname(name))\n\t\t}\n\t}\n\n\t// Resume from checkpoint if available\n\tif (options.checkpoint && options.checkpoint.UploadId) {\n\t\t// Update file reference in checkpoint\n\t\tif (file) options.checkpoint.file = file\n\n\t\treturn resumeMultipart(options.checkpoint, params, options)\n\t}\n\n\toptions.headers = options.headers || {}\n\n\tconst fileSize = file.size\n\n\t// Use simple upload for files smaller than minimum part size\n\tif (fileSize < S3_MIN_PART_SIZE) {\n\t\treturn STSUpload(file, key, params, { ...options })\n\t}\n\n\t// Validate part size\n\tif (options.partSize && !(parseInt(String(options.partSize), 10) === options.partSize)) {\n\t\tthrow new InitException(InitExceptionCode.UPLOAD_API_OPTION_PARTSIZE_MUST_INT)\n\t}\n\n\tif (options.partSize && options.partSize < S3_MIN_PART_SIZE) {\n\t\tthrow new InitException(\n\t\t\tInitExceptionCode.UPLOAD_API_OPTION_PARTSIZE_IS_SMALL,\n\t\t\tS3_MIN_PART_SIZE,\n\t\t)\n\t}\n\n\t// Initialize multipart upload\n\tconst taskId = options.taskId\n\tconst initAbortSignal = taskId ? createAbortSignal(taskId) : undefined\n\tconst { UploadId } = await initMultipartUpload(name, params, {\n\t\theaders: { ...options.headers },\n\t\tmime: options.mime,\n\t}, initAbortSignal, taskId)\n\n\t// Calculate part size\n\tconst partSize = getPartSize(fileSize, <number>options.partSize, S3_MIN_PART_SIZE)\n\n\tconst checkpoint: MinIO.Checkpoint = initCheckpoint(file, name, fileSize, partSize, UploadId)\n\n\tif (options && options.progress) {\n\t\toptions.progress(0, 0, fileSize, checkpoint)\n\t}\n\n\treturn resumeMultipart(checkpoint, params, options)\n}\n\n\n\n\n\n"],"mappings":"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","names":[]}
|