@maiyunnet/kebab 9.20.0 → 9.20.1
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/doc/kebab-rag.md +31 -15
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/lib/s3.d.ts +13 -3
- package/lib/s3.js +94 -15
- package/package.json +1 -1
package/doc/kebab-rag.md
CHANGED
|
@@ -1589,7 +1589,7 @@ index/variables/VER.md
|
|
|
1589
1589
|
|
|
1590
1590
|
# Variable: VER
|
|
1591
1591
|
|
|
1592
|
-
> `const` **VER**: `"9.20.
|
|
1592
|
+
> `const` **VER**: `"9.20.1"` = `'9.20.1'`
|
|
1593
1593
|
|
|
1594
1594
|
Defined in: [index.ts:10](https://github.com/maiyunnet/kebab/blob/master/index.ts#L10)
|
|
1595
1595
|
|
|
@@ -122018,7 +122018,7 @@ Defined in: [lib/s3.ts:88](https://github.com/maiyunnet/kebab/blob/master/lib/s3
|
|
|
122018
122018
|
|
|
122019
122019
|
> **deleteObject**(`key`, `bucket?`): `Promise`\<`boolean`\>
|
|
122020
122020
|
|
|
122021
|
-
Defined in: [lib/s3.ts:
|
|
122021
|
+
Defined in: [lib/s3.ts:367](https://github.com/maiyunnet/kebab/blob/master/lib/s3.ts#L367)
|
|
122022
122022
|
|
|
122023
122023
|
删除对象
|
|
122024
122024
|
|
|
@@ -122046,7 +122046,7 @@ bucket 名
|
|
|
122046
122046
|
|
|
122047
122047
|
> **deleteObjects**(`keys`, `bucket?`): `Promise`\<`boolean`\>
|
|
122048
122048
|
|
|
122049
|
-
Defined in: [lib/s3.ts:
|
|
122049
|
+
Defined in: [lib/s3.ts:387](https://github.com/maiyunnet/kebab/blob/master/lib/s3.ts#L387)
|
|
122050
122050
|
|
|
122051
122051
|
批量删除对象
|
|
122052
122052
|
|
|
@@ -122074,7 +122074,7 @@ bucket 名
|
|
|
122074
122074
|
|
|
122075
122075
|
> **destroy**(): `void`
|
|
122076
122076
|
|
|
122077
|
-
Defined in: [lib/s3.ts:
|
|
122077
|
+
Defined in: [lib/s3.ts:429](https://github.com/maiyunnet/kebab/blob/master/lib/s3.ts#L429)
|
|
122078
122078
|
|
|
122079
122079
|
销毁连接,释放资源
|
|
122080
122080
|
一般会自动垃圾回收,但高频接口也可主动调用
|
|
@@ -122089,7 +122089,7 @@ Defined in: [lib/s3.ts:341](https://github.com/maiyunnet/kebab/blob/master/lib/s
|
|
|
122089
122089
|
|
|
122090
122090
|
> **getObject**(`key`, `bucket?`): `Promise`\<`false` \| `Readable` & `SdkStreamMixin` \| `Blob` & `SdkStreamMixin` \| `ReadableStream`\<`any`\> & `SdkStreamMixin` \| `undefined`\>
|
|
122091
122091
|
|
|
122092
|
-
Defined in: [lib/s3.ts:
|
|
122092
|
+
Defined in: [lib/s3.ts:323](https://github.com/maiyunnet/kebab/blob/master/lib/s3.ts#L323)
|
|
122093
122093
|
|
|
122094
122094
|
获取对象流,可通过流获取 buffer 或 text
|
|
122095
122095
|
|
|
@@ -122117,7 +122117,7 @@ bucket 名
|
|
|
122117
122117
|
|
|
122118
122118
|
> **getObjectBuffer**(`key`, `bucket?`): `Promise`\<`false` \| `Buffer`\<`ArrayBufferLike`\>\>
|
|
122119
122119
|
|
|
122120
|
-
Defined in: [lib/s3.ts:
|
|
122120
|
+
Defined in: [lib/s3.ts:344](https://github.com/maiyunnet/kebab/blob/master/lib/s3.ts#L344)
|
|
122121
122121
|
|
|
122122
122122
|
获取对象 Buffer
|
|
122123
122123
|
|
|
@@ -122147,7 +122147,7 @@ bucket 名
|
|
|
122147
122147
|
|
|
122148
122148
|
> **headObject**(`key`, `bucket?`): `Promise`\<`false` \| `HeadObjectCommandOutput`\>
|
|
122149
122149
|
|
|
122150
|
-
Defined in: [lib/s3.ts:
|
|
122150
|
+
Defined in: [lib/s3.ts:409](https://github.com/maiyunnet/kebab/blob/master/lib/s3.ts#L409)
|
|
122151
122151
|
|
|
122152
122152
|
检测对象是否存在
|
|
122153
122153
|
|
|
@@ -122175,9 +122175,9 @@ bucket 名
|
|
|
122175
122175
|
|
|
122176
122176
|
> **putObject**(`key`, `content`, `length?`, `bucket?`): `Promise`\<`false` \| `CompleteMultipartUploadCommandOutput`\>
|
|
122177
122177
|
|
|
122178
|
-
Defined in: [lib/s3.ts:
|
|
122178
|
+
Defined in: [lib/s3.ts:140](https://github.com/maiyunnet/kebab/blob/master/lib/s3.ts#L140)
|
|
122179
122179
|
|
|
122180
|
-
|
|
122180
|
+
上传对象,流内容可省略 length
|
|
122181
122181
|
|
|
122182
122182
|
#### Parameters
|
|
122183
122183
|
|
|
@@ -122195,9 +122195,9 @@ Defined in: [lib/s3.ts:139](https://github.com/maiyunnet/kebab/blob/master/lib/s
|
|
|
122195
122195
|
|
|
122196
122196
|
##### length?
|
|
122197
122197
|
|
|
122198
|
-
`number` \| \{ `bucket?`: `string`; `disposition?`: `string`; `length?`: `number`; `type?`: `string`; \}
|
|
122198
|
+
`number` \| \{ `bucket?`: `string`; `disposition?`: `string`; `length?`: `number`; `signal?`: `AbortSignal`; `type?`: `string`; \}
|
|
122199
122199
|
|
|
122200
|
-
|
|
122200
|
+
contentLength 或上传选项
|
|
122201
122201
|
|
|
122202
122202
|
`number`
|
|
122203
122203
|
|
|
@@ -122205,22 +122205,36 @@ Defined in: [lib/s3.ts:139](https://github.com/maiyunnet/kebab/blob/master/lib/s
|
|
|
122205
122205
|
|
|
122206
122206
|
###### Type Literal
|
|
122207
122207
|
|
|
122208
|
-
\{ `bucket?`: `string`; `disposition?`: `string`; `length?`: `number`; `type?`: `string`; \}
|
|
122208
|
+
\{ `bucket?`: `string`; `disposition?`: `string`; `length?`: `number`; `signal?`: `AbortSignal`; `type?`: `string`; \}
|
|
122209
122209
|
|
|
122210
|
-
|
|
122210
|
+
contentLength 或上传选项
|
|
122211
122211
|
|
|
122212
122212
|
###### bucket?
|
|
122213
122213
|
|
|
122214
122214
|
`string`
|
|
122215
122215
|
|
|
122216
|
+
bucket 名,省略时使用预定义 bucket
|
|
122217
|
+
|
|
122216
122218
|
###### disposition?
|
|
122217
122219
|
|
|
122218
122220
|
`string`
|
|
122219
122221
|
|
|
122222
|
+
content-disposition,如 attachment
|
|
122223
|
+
|
|
122220
122224
|
###### length?
|
|
122221
122225
|
|
|
122222
122226
|
`number`
|
|
122223
122227
|
|
|
122228
|
+
contentLength,流内容可省略
|
|
122229
|
+
|
|
122230
|
+
###### signal?
|
|
122231
|
+
|
|
122232
|
+
`AbortSignal`
|
|
122233
|
+
|
|
122234
|
+
取消上传请求并销毁输入流,等待已知的未完成分片清理后返回 false
|
|
122235
|
+
清理使用独立的 30 秒超时信号,失败时记录错误;不传则沿用原上传流程
|
|
122236
|
+
不删除同名对象,上传完成与取消同时发生时,由调用方清理独立任务文件
|
|
122237
|
+
|
|
122224
122238
|
###### type?
|
|
122225
122239
|
|
|
122226
122240
|
`string`
|
|
@@ -122237,13 +122251,15 @@ bucket 名
|
|
|
122237
122251
|
|
|
122238
122252
|
`Promise`\<`false` \| `CompleteMultipartUploadCommandOutput`\>
|
|
122239
122253
|
|
|
122254
|
+
上传结果,失败或取消返回 false;传入 signal 时,返回前会尝试清理已知的未完成分片
|
|
122255
|
+
|
|
122240
122256
|
***
|
|
122241
122257
|
|
|
122242
122258
|
### putObjects()
|
|
122243
122259
|
|
|
122244
122260
|
> **putObjects**(`items`, `options?`): `Promise`\<[`IPutObjectsItemResult`](../interfaces/IPutObjectsItemResult.md)[]\>
|
|
122245
122261
|
|
|
122246
|
-
Defined in: [lib/s3.ts:
|
|
122262
|
+
Defined in: [lib/s3.ts:272](https://github.com/maiyunnet/kebab/blob/master/lib/s3.ts#L272)
|
|
122247
122263
|
|
|
122248
122264
|
批量上传对象,并发控制,单次失败不影响其他项
|
|
122249
122265
|
|
|
@@ -122347,7 +122363,7 @@ lib/s3/functions/get.md
|
|
|
122347
122363
|
|
|
122348
122364
|
> **get**(`ctr`, `opt`): [`S3`](../classes/S3.md)
|
|
122349
122365
|
|
|
122350
|
-
Defined in: [lib/s3.ts:
|
|
122366
|
+
Defined in: [lib/s3.ts:439](https://github.com/maiyunnet/kebab/blob/master/lib/s3.ts#L439)
|
|
122351
122367
|
|
|
122352
122368
|
创建一个对象存储对象
|
|
122353
122369
|
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* --- 本文件用来定义每个目录实体地址的常量 ---
|
|
7
7
|
*/
|
|
8
8
|
/** --- 当前系统版本号 --- */
|
|
9
|
-
export const VER = '9.20.
|
|
9
|
+
export const VER = '9.20.1';
|
|
10
10
|
// --- 服务端用的路径 ---
|
|
11
11
|
const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
|
|
12
12
|
/** --- /xxx/xxx --- */
|
package/lib/s3.d.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Date: 2024-2-18 18:32:45
|
|
4
4
|
* Last: 2024-2-18 18:32:47, 2024-3-16 16:42:27, 2024-5-31 21:36:26, 2024-7-8 00:28:42, 2024-7-19 11:32:43, 2025-6-10 21:45:34, 2025-12-5 23:42:59
|
|
5
5
|
*/
|
|
6
|
-
import * as s3 from '@aws-sdk/client-s3';
|
|
7
6
|
import * as stream from 'stream';
|
|
7
|
+
import * as s3 from '@aws-sdk/client-s3';
|
|
8
8
|
import * as sCtr from '#kebab/sys/ctr.js';
|
|
9
9
|
/**
|
|
10
10
|
* --- s3 文档:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/ ---
|
|
@@ -76,18 +76,28 @@ export declare class S3 {
|
|
|
76
76
|
*/
|
|
77
77
|
setBucket(bucket: string): void;
|
|
78
78
|
/**
|
|
79
|
-
* ---
|
|
79
|
+
* --- 上传对象,流内容可省略 length ---
|
|
80
80
|
* @param key 对象路径
|
|
81
81
|
* @param content 内容
|
|
82
|
-
* @param length
|
|
82
|
+
* @param length contentLength 或上传选项
|
|
83
83
|
* @param bucket bucket 名
|
|
84
|
+
* @returns 上传结果,失败或取消返回 false;传入 signal 时,返回前会尝试清理已知的未完成分片
|
|
84
85
|
*/
|
|
85
86
|
putObject(key: string, content: string | Buffer | stream.Readable, length?: number | {
|
|
87
|
+
/** --- contentLength,流内容可省略 --- */
|
|
86
88
|
'length'?: number;
|
|
87
89
|
/** --- content-type,如 application/javascript --- */
|
|
88
90
|
'type'?: string;
|
|
91
|
+
/** --- content-disposition,如 attachment --- */
|
|
89
92
|
'disposition'?: string;
|
|
93
|
+
/** --- bucket 名,省略时使用预定义 bucket --- */
|
|
90
94
|
'bucket'?: string;
|
|
95
|
+
/**
|
|
96
|
+
* --- 取消上传请求并销毁输入流,等待已知的未完成分片清理后返回 false ---
|
|
97
|
+
* --- 清理使用独立的 30 秒超时信号,失败时记录错误;不传则沿用原上传流程 ---
|
|
98
|
+
* --- 不删除同名对象,上传完成与取消同时发生时,由调用方清理独立任务文件 ---
|
|
99
|
+
*/
|
|
100
|
+
'signal'?: AbortSignal;
|
|
91
101
|
}, bucket?: string): Promise<s3.CompleteMultipartUploadCommandOutput | false>;
|
|
92
102
|
/**
|
|
93
103
|
* --- 批量上传对象,并发控制,单次失败不影响其他项 ---
|
package/lib/s3.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Last: 2024-2-18 18:32:47, 2024-3-16 16:42:27, 2024-5-31 21:36:26, 2024-7-8 00:28:42, 2024-7-19 11:32:43, 2025-6-10 21:45:34, 2025-12-5 23:42:59
|
|
5
5
|
*/
|
|
6
6
|
// --- 库和定义 ---
|
|
7
|
+
import * as stream from 'stream';
|
|
7
8
|
import * as s3 from '@aws-sdk/client-s3';
|
|
8
9
|
import * as ls from '@aws-sdk/lib-storage';
|
|
9
10
|
import * as lCore from '#kebab/lib/core.js';
|
|
@@ -67,28 +68,79 @@ export class S3 {
|
|
|
67
68
|
this._bucket = bucket;
|
|
68
69
|
}
|
|
69
70
|
/**
|
|
70
|
-
* ---
|
|
71
|
+
* --- 上传对象,流内容可省略 length ---
|
|
71
72
|
* @param key 对象路径
|
|
72
73
|
* @param content 内容
|
|
73
|
-
* @param length
|
|
74
|
+
* @param length contentLength 或上传选项
|
|
74
75
|
* @param bucket bucket 名
|
|
76
|
+
* @returns 上传结果,失败或取消返回 false;传入 signal 时,返回前会尝试清理已知的未完成分片
|
|
75
77
|
*/
|
|
76
78
|
async putObject(key, content, length, bucket) {
|
|
79
|
+
/** --- 对象内容类型 --- */
|
|
80
|
+
let type;
|
|
81
|
+
/** --- 对象下载方式 --- */
|
|
82
|
+
let disposition;
|
|
83
|
+
/** --- 调用方传入的取消信号,仅作用于本次上传 --- */
|
|
84
|
+
let signal;
|
|
85
|
+
if (typeof length !== 'number') {
|
|
86
|
+
type = length?.type;
|
|
87
|
+
disposition = length?.disposition;
|
|
88
|
+
bucket = length?.bucket;
|
|
89
|
+
signal = length?.signal;
|
|
90
|
+
length = length?.length;
|
|
91
|
+
}
|
|
92
|
+
bucket ??= this._bucket;
|
|
93
|
+
/** --- 输入流,传入 signal 时在取消或失败后停止读取;字符串与 Buffer 无需释放 --- */
|
|
94
|
+
const source = content instanceof stream.Readable ? content : undefined;
|
|
95
|
+
/**
|
|
96
|
+
* --- 停止流读取,避免取消时仍阻塞在等待下一块数据的阶段 ---
|
|
97
|
+
* @returns 无返回值
|
|
98
|
+
*/
|
|
99
|
+
const onAbort = () => {
|
|
100
|
+
source?.destroy();
|
|
101
|
+
};
|
|
102
|
+
/** --- 尚未确认合并或清理完成的分片上传 ID,用于失败后的兜底清理 --- */
|
|
103
|
+
let uploadId;
|
|
104
|
+
/** --- 是否取得有效上传结果,失败时需要释放输入流 --- */
|
|
105
|
+
let success = false;
|
|
106
|
+
/** --- 分片清理请求的超时毫秒数,避免清理阶段无限等待 --- */
|
|
107
|
+
const cleanupTimeout = 30000;
|
|
77
108
|
try {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
/** --- content disposition --- */
|
|
81
|
-
let disposition = undefined;
|
|
82
|
-
if (typeof length !== 'number') {
|
|
83
|
-
type = length?.type;
|
|
84
|
-
disposition = length?.disposition;
|
|
85
|
-
bucket = length?.bucket;
|
|
86
|
-
length = length?.length;
|
|
109
|
+
if (signal?.aborted) {
|
|
110
|
+
return false;
|
|
87
111
|
}
|
|
112
|
+
signal?.addEventListener('abort', onAbort, { 'once': true });
|
|
113
|
+
/** --- 本次上传的客户端入口,共享连接配置但不修改共享客户端的 send --- */
|
|
114
|
+
const client = signal ? Object.create(this._link) : this._link;
|
|
115
|
+
if (signal) {
|
|
116
|
+
/**
|
|
117
|
+
* --- 为上传命令传递取消信号,并跟踪未完成的分片上传 ---
|
|
118
|
+
* --- Upload.abort() 会提前结束 done(),且不会取消正在发送的请求 ---
|
|
119
|
+
* --- 逐条命令传入信号,让 done() 等待分片任务和清理结束 ---
|
|
120
|
+
* @param command SDK 上传或分片清理命令;Upload 仅使用 send 的 Promise 调用形式
|
|
121
|
+
* @returns SDK 命令结果
|
|
122
|
+
*/
|
|
123
|
+
client.send = (async (command) => {
|
|
124
|
+
/** --- 清理请求必须使用独立信号,避免随上传请求一起取消 --- */
|
|
125
|
+
const isCleanup = command instanceof s3.AbortMultipartUploadCommand;
|
|
126
|
+
/** --- 命令成功后再更新分片 ID,失败时保留 ID 供 finally 重试清理 --- */
|
|
127
|
+
const res = await this._link.send(command, {
|
|
128
|
+
'abortSignal': isCleanup ? AbortSignal.timeout(cleanupTimeout) : signal,
|
|
129
|
+
});
|
|
130
|
+
if (command instanceof s3.CreateMultipartUploadCommand) {
|
|
131
|
+
uploadId = res.UploadId;
|
|
132
|
+
}
|
|
133
|
+
else if (isCleanup || (command instanceof s3.CompleteMultipartUploadCommand)) {
|
|
134
|
+
uploadId = undefined;
|
|
135
|
+
}
|
|
136
|
+
return res;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/** --- SDK 上传任务,继续由 SDK 管理分片和并发 --- */
|
|
88
140
|
const upload = new ls.Upload({
|
|
89
|
-
'client':
|
|
141
|
+
'client': client,
|
|
90
142
|
'params': {
|
|
91
|
-
'Bucket': bucket
|
|
143
|
+
'Bucket': bucket,
|
|
92
144
|
'Key': key,
|
|
93
145
|
'Body': content,
|
|
94
146
|
'ContentLength': length,
|
|
@@ -96,13 +148,40 @@ export class S3 {
|
|
|
96
148
|
'ContentDisposition': disposition,
|
|
97
149
|
}
|
|
98
150
|
});
|
|
151
|
+
/** --- 上传结果;取消与上传完成同时发生时仍向调用方返回 false --- */
|
|
99
152
|
const res = await upload.done();
|
|
100
|
-
|
|
153
|
+
if (signal?.aborted || !res.Location || !res.Bucket || !res.Key) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
success = true;
|
|
157
|
+
return res;
|
|
101
158
|
}
|
|
102
159
|
catch (e) {
|
|
103
|
-
|
|
160
|
+
if (!signal?.aborted) {
|
|
161
|
+
lCore.log(this._ctr, `[LIB][S3][putObject] ${lText.stringifyError(e)}`, '-error');
|
|
162
|
+
}
|
|
104
163
|
return false;
|
|
105
164
|
}
|
|
165
|
+
finally {
|
|
166
|
+
signal?.removeEventListener('abort', onAbort);
|
|
167
|
+
if (signal && !success) {
|
|
168
|
+
source?.destroy();
|
|
169
|
+
}
|
|
170
|
+
// --- SDK 的合并失败分支不会清理分片;SDK 清理失败时也保留 ID,在这里兜底 ---
|
|
171
|
+
// --- 只清理本次未完成的分片,不删除可能已存在的同名对象 ---
|
|
172
|
+
if (uploadId) {
|
|
173
|
+
try {
|
|
174
|
+
await this._link.send(new s3.AbortMultipartUploadCommand({
|
|
175
|
+
'Bucket': bucket,
|
|
176
|
+
'Key': key,
|
|
177
|
+
'UploadId': uploadId,
|
|
178
|
+
}), { 'abortSignal': AbortSignal.timeout(cleanupTimeout) });
|
|
179
|
+
}
|
|
180
|
+
catch (e) {
|
|
181
|
+
lCore.log(this._ctr, `[LIB][S3][putObject][cleanup] ${lText.stringifyError(e)}`, '-error');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
106
185
|
}
|
|
107
186
|
/**
|
|
108
187
|
* --- 批量上传对象,并发控制,单次失败不影响其他项 ---
|