@kevisual/oss 0.0.17 → 0.0.19

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/dist/services.js CHANGED
@@ -36456,15 +36456,21 @@ class OssBase {
36456
36456
  contentLength = Buffer.byteLength(putData);
36457
36457
  }
36458
36458
  } else {
36459
- putData = data;
36460
36459
  if (!contentLength) {
36461
- throw new Error("Stream upload requires size parameter");
36460
+ const chunks = [];
36461
+ for await (const chunk of data) {
36462
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
36463
+ }
36464
+ putData = Buffer.concat(chunks);
36465
+ contentLength = putData.length;
36466
+ } else {
36467
+ putData = data;
36462
36468
  }
36463
36469
  }
36464
36470
  if (opts?.check) {
36465
36471
  const obj = await this.statObject(objectName, true);
36466
36472
  if (obj) {
36467
- const omitMeta = ["size", "Content-Type", "Cache-Control", "app-source"];
36473
+ const omitMeta = ["size", "content-type", "cache-control", "app-source"];
36468
36474
  const objMeta = JSON.parse(JSON.stringify(omit(obj.metaData, omitMeta)));
36469
36475
  metaData = {
36470
36476
  ...objMeta,
@@ -36493,22 +36499,41 @@ class OssBase {
36493
36499
  };
36494
36500
  }
36495
36501
  async fPutObject(objectName, filePath, metaData) {
36496
- const fileStream = fs.createReadStream(filePath);
36497
36502
  const stat = fs.statSync(filePath);
36498
36503
  const { standardHeaders, customMetadata } = extractStandardHeaders(metaData || {});
36499
- const command = new import_client_s3.PutObjectCommand({
36500
- Bucket: this.bucketName,
36501
- Key: `${this.prefix}${objectName}`,
36502
- Body: fileStream,
36503
- ContentLength: stat.size,
36504
- ContentType: standardHeaders.ContentType || getContentType(filePath),
36505
- CacheControl: standardHeaders.CacheControl,
36506
- ContentDisposition: standardHeaders.ContentDisposition,
36507
- ContentEncoding: standardHeaders.ContentEncoding,
36508
- ContentLanguage: standardHeaders.ContentLanguage,
36509
- Expires: standardHeaders.Expires,
36510
- Metadata: customMetadata
36511
- });
36504
+ const THRESHOLD = 5 * 1024 * 1024;
36505
+ let command;
36506
+ if (stat.size < THRESHOLD) {
36507
+ const fileBuffer = await fs.promises.readFile(filePath);
36508
+ command = new import_client_s3.PutObjectCommand({
36509
+ Bucket: this.bucketName,
36510
+ Key: `${this.prefix}${objectName}`,
36511
+ Body: fileBuffer,
36512
+ ContentLength: fileBuffer.length,
36513
+ ContentType: standardHeaders.ContentType || getContentType(filePath),
36514
+ CacheControl: standardHeaders.CacheControl,
36515
+ ContentDisposition: standardHeaders.ContentDisposition,
36516
+ ContentEncoding: standardHeaders.ContentEncoding,
36517
+ ContentLanguage: standardHeaders.ContentLanguage,
36518
+ Expires: standardHeaders.Expires,
36519
+ Metadata: customMetadata
36520
+ });
36521
+ } else {
36522
+ const fileStream = fs.createReadStream(filePath);
36523
+ command = new import_client_s3.PutObjectCommand({
36524
+ Bucket: this.bucketName,
36525
+ Key: `${this.prefix}${objectName}`,
36526
+ Body: fileStream,
36527
+ ContentLength: stat.size,
36528
+ ContentType: standardHeaders.ContentType || getContentType(filePath),
36529
+ CacheControl: standardHeaders.CacheControl,
36530
+ ContentDisposition: standardHeaders.ContentDisposition,
36531
+ ContentEncoding: standardHeaders.ContentEncoding,
36532
+ ContentLanguage: standardHeaders.ContentLanguage,
36533
+ Expires: standardHeaders.Expires,
36534
+ Metadata: customMetadata
36535
+ });
36536
+ }
36512
36537
  const response = await this.client.send(command);
36513
36538
  return {
36514
36539
  etag: response.ETag?.replace(/"/g, "") || "",
@@ -36531,6 +36556,7 @@ class OssBase {
36531
36556
  const prefix = `${this.prefix}${objectName}`;
36532
36557
  const results = [];
36533
36558
  let continuationToken;
36559
+ const getMeta = opts?.getMeta ?? false;
36534
36560
  do {
36535
36561
  const command = new import_client_s3.ListObjectsV2Command({
36536
36562
  Bucket: this.bucketName,
@@ -36543,12 +36569,19 @@ class OssBase {
36543
36569
  const response = await this.client.send(command);
36544
36570
  if (response.Contents) {
36545
36571
  for (const item of response.Contents) {
36546
- results.push({
36572
+ const result = {
36547
36573
  name: item.Key || "",
36548
36574
  size: item.Size || 0,
36549
36575
  lastModified: item.LastModified || new Date,
36550
36576
  etag: item.ETag?.replace(/"/g, "") || ""
36551
- });
36577
+ };
36578
+ if (getMeta) {
36579
+ const stat = await this.statObject(item.Key || "", false);
36580
+ if (stat?.metaData) {
36581
+ result.metaData = stat.metaData;
36582
+ }
36583
+ }
36584
+ results.push(result);
36552
36585
  }
36553
36586
  }
36554
36587
  if (response.CommonPrefixes && !opts?.recursive) {
@@ -36571,6 +36604,13 @@ class OssBase {
36571
36604
  });
36572
36605
  const response = await this.client.send(command);
36573
36606
  return {
36607
+ standardHeaders: {
36608
+ contentType: response.ContentType,
36609
+ cacheControl: response.CacheControl,
36610
+ contentDisposition: response.ContentDisposition,
36611
+ contentEncoding: response.ContentEncoding,
36612
+ contentLanguage: response.ContentLanguage
36613
+ },
36574
36614
  size: response.ContentLength || 0,
36575
36615
  etag: response.ETag?.replace?.(/"/g, "") || "",
36576
36616
  lastModified: response.LastModified || new Date,
@@ -36578,11 +36618,11 @@ class OssBase {
36578
36618
  versionId: response.VersionId || null
36579
36619
  };
36580
36620
  } catch (e) {
36581
- console.error("statObject error", e);
36582
36621
  const isNotFound = e.name === "NotFound" || e.name === "NoSuchBucket" || e.name === "NoSuchKey" || e.code === "NotFound" || e.code === "NoSuchBucket" || e.code === "NoSuchKey" || e.$metadata?.httpStatusCode === 404;
36583
36622
  if (checkFile && isNotFound) {
36584
36623
  return null;
36585
36624
  }
36625
+ console.error("statObject error", e);
36586
36626
  throw e;
36587
36627
  }
36588
36628
  }
@@ -36723,69 +36763,12 @@ class ConfigOssService extends OssBase {
36723
36763
  return { list: listKeys, keys, keyEtagMap };
36724
36764
  }
36725
36765
  }
36726
- // src/util/download.ts
36727
- import fs2 from "node:fs";
36728
- import path2 from "node:path";
36729
- var viewableExtensions = ["jpg", "jpeg", "png", "gif", "svg", "webp", "mp4", "webm", "mp3", "wav", "ogg", "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx"];
36730
- var filterMetaDataKeys = (metaData, clearKeys = []) => {
36731
- const keys = Object.keys(metaData);
36732
- const removeKeys = ["password", "accesskey", "secretkey", ...clearKeys];
36733
- const filteredKeys = keys.filter((key) => !removeKeys.includes(key));
36734
- return filteredKeys.reduce((acc, key) => {
36735
- acc[key] = metaData[key];
36736
- return acc;
36737
- }, {});
36738
- };
36739
- var NotFoundFile = (res, msg, code = 404) => {
36740
- res.writeHead(code, { "Content-Type": "text/plain" });
36741
- res.end(msg || "Not Found File");
36742
- return;
36743
- };
36744
- var sendObject = async ({ res, objectName, client, isDownload = false }) => {
36745
- let stat;
36746
- try {
36747
- stat = await client.statObject(objectName);
36748
- } catch (e) {} finally {
36749
- if (!stat || stat.size === 0) {
36750
- return NotFoundFile(res);
36751
- }
36752
- const contentLength = stat.size;
36753
- const etag = stat.etag;
36754
- const lastModified = stat.lastModified.toISOString();
36755
- const filename = objectName.split("/").pop() || "no-file-name-download";
36756
- const fileExtension = filename.split(".").pop()?.toLowerCase() || "";
36757
- const filteredMetaData = filterMetaDataKeys(stat.metaData, ["size", "etag", "last-modified"]);
36758
- const contentDisposition = viewableExtensions.includes(fileExtension) && !isDownload ? "inline" : `attachment; filename="${filename}"`;
36759
- res.writeHead(200, {
36760
- "Content-Length": contentLength,
36761
- etag,
36762
- "last-modified": lastModified,
36763
- "Content-Disposition": contentDisposition,
36764
- ...filteredMetaData
36765
- });
36766
- const objectStream = await client.getObject(objectName);
36767
- objectStream.pipe(res, { end: true });
36768
- }
36769
- };
36770
- var downloadObject = async ({ objectName, client, filePath }) => {
36771
- const objectStream = await client.getObject(objectName);
36772
- const dir = path2.dirname(filePath);
36773
- if (!fs2.existsSync(dir)) {
36774
- fs2.mkdirSync(dir, { recursive: true });
36775
- }
36776
- objectStream.pipe(fs2.createWriteStream(filePath));
36777
- return objectStream;
36778
- };
36779
36766
  export {
36780
36767
  standardHeaderKeys,
36781
- sendObject,
36782
36768
  hashSringify,
36783
36769
  hash,
36784
36770
  getContentType,
36785
- filterMetaDataKeys,
36786
36771
  extractStandardHeaders,
36787
- downloadObject,
36788
36772
  OssBase,
36789
- NotFoundFile,
36790
36773
  ConfigOssService
36791
36774
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kevisual/oss",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "build": "bun run bun.config.ts"
@@ -21,8 +21,7 @@
21
21
  "bun-plugin-dts": "^0.3.0",
22
22
  "dotenv": "^17.2.3",
23
23
  "es-toolkit": "^1.44.0",
24
- "fast-glob": "^3.3.3",
25
- "minio": "^8.0.6"
24
+ "fast-glob": "^3.3.3"
26
25
  },
27
26
  "exports": {
28
27
  ".": {
package/src/index.ts CHANGED
@@ -1 +1,3 @@
1
- export * from './s3/core.ts'
1
+ export * from './s3/core.ts'
2
+
3
+ export * from './s3/type.ts'
package/src/s3/core.ts CHANGED
@@ -127,9 +127,16 @@ export class OssBase implements OssBaseOperation {
127
127
  contentLength = Buffer.byteLength(putData);
128
128
  }
129
129
  } else {
130
- putData = data as Readable;
130
+ // Stream 上传:自动读取到 Buffer 以获取 contentLength
131
131
  if (!contentLength) {
132
- throw new Error('Stream upload requires size parameter');
132
+ const chunks: Buffer[] = [];
133
+ for await (const chunk of data as Readable) {
134
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
135
+ }
136
+ putData = Buffer.concat(chunks);
137
+ contentLength = putData.length;
138
+ } else {
139
+ putData = data as Readable;
133
140
  }
134
141
  }
135
142
 
@@ -137,7 +144,7 @@ export class OssBase implements OssBaseOperation {
137
144
  if (opts?.check) {
138
145
  const obj = await this.statObject(objectName, true);
139
146
  if (obj) {
140
- const omitMeta = ['size', 'Content-Type', 'Cache-Control', 'app-source'];
147
+ const omitMeta = ['size', 'content-type', 'cache-control', 'app-source'];
141
148
  const objMeta = JSON.parse(JSON.stringify(omit(obj.metaData, omitMeta)));
142
149
  metaData = {
143
150
  ...objMeta,
@@ -180,24 +187,45 @@ export class OssBase implements OssBaseOperation {
180
187
  filePath: string,
181
188
  metaData?: ItemBucketMetadata,
182
189
  ): Promise<UploadedObjectInfo> {
183
- const fileStream = fs.createReadStream(filePath);
184
190
  const stat = fs.statSync(filePath);
185
-
186
191
  const { standardHeaders, customMetadata } = extractStandardHeaders(metaData || {});
187
192
 
188
- const command = new PutObjectCommand({
189
- Bucket: this.bucketName,
190
- Key: `${this.prefix}${objectName}`,
191
- Body: fileStream,
192
- ContentLength: stat.size,
193
- ContentType: standardHeaders.ContentType || getContentType(filePath),
194
- CacheControl: standardHeaders.CacheControl,
195
- ContentDisposition: standardHeaders.ContentDisposition,
196
- ContentEncoding: standardHeaders.ContentEncoding,
197
- ContentLanguage: standardHeaders.ContentLanguage,
198
- Expires: standardHeaders.Expires,
199
- Metadata: customMetadata,
200
- });
193
+ const THRESHOLD = 5 * 1024 * 1024; // 5MB
194
+ let command: PutObjectCommand;
195
+
196
+ if (stat.size < THRESHOLD) {
197
+ // 小文件:读取到内存再上传,避免流式传输导致的 IncompleteBody 错误
198
+ const fileBuffer = await fs.promises.readFile(filePath);
199
+ command = new PutObjectCommand({
200
+ Bucket: this.bucketName,
201
+ Key: `${this.prefix}${objectName}`,
202
+ Body: fileBuffer,
203
+ ContentLength: fileBuffer.length,
204
+ ContentType: standardHeaders.ContentType || getContentType(filePath),
205
+ CacheControl: standardHeaders.CacheControl,
206
+ ContentDisposition: standardHeaders.ContentDisposition,
207
+ ContentEncoding: standardHeaders.ContentEncoding,
208
+ ContentLanguage: standardHeaders.ContentLanguage,
209
+ Expires: standardHeaders.Expires,
210
+ Metadata: customMetadata,
211
+ });
212
+ } else {
213
+ // 大文件:使用流式上传
214
+ const fileStream = fs.createReadStream(filePath);
215
+ command = new PutObjectCommand({
216
+ Bucket: this.bucketName,
217
+ Key: `${this.prefix}${objectName}`,
218
+ Body: fileStream,
219
+ ContentLength: stat.size,
220
+ ContentType: standardHeaders.ContentType || getContentType(filePath),
221
+ CacheControl: standardHeaders.CacheControl,
222
+ ContentDisposition: standardHeaders.ContentDisposition,
223
+ ContentEncoding: standardHeaders.ContentEncoding,
224
+ ContentLanguage: standardHeaders.ContentLanguage,
225
+ Expires: standardHeaders.Expires,
226
+ Metadata: customMetadata,
227
+ });
228
+ }
201
229
 
202
230
  const response = await this.client.send(command);
203
231
  return {
@@ -230,12 +258,12 @@ export class OssBase implements OssBaseOperation {
230
258
  */
231
259
  async listObjects<IS_FILE = false>(
232
260
  objectName: string,
233
- opts?: { recursive?: boolean; startAfter?: string; maxKeys?: number },
261
+ opts?: { recursive?: boolean; startAfter?: string; maxKeys?: number, getMeta?: boolean },
234
262
  ): Promise<IS_FILE extends true ? ListFileObject[] : ListObjectResult[]> {
235
263
  const prefix = `${this.prefix}${objectName}`;
236
264
  const results: ListObjectResult[] = [];
237
265
  let continuationToken: string | undefined;
238
-
266
+ const getMeta = opts?.getMeta ?? false;
239
267
  do {
240
268
  const command = new ListObjectsV2Command({
241
269
  Bucket: this.bucketName,
@@ -251,12 +279,19 @@ export class OssBase implements OssBaseOperation {
251
279
  // 处理文件对象
252
280
  if (response.Contents) {
253
281
  for (const item of response.Contents) {
254
- results.push({
282
+ const result: ListFileObject = {
255
283
  name: item.Key || '',
256
284
  size: item.Size || 0,
257
285
  lastModified: item.LastModified || new Date(),
258
286
  etag: item.ETag?.replace(/"/g, '') || '',
259
- });
287
+ }
288
+ if (getMeta) {
289
+ const stat = await this.statObject(item.Key || '', false);
290
+ if (stat?.metaData) {
291
+ result.metaData = stat.metaData;
292
+ }
293
+ }
294
+ results.push(result);
260
295
  }
261
296
  }
262
297
 
@@ -290,6 +325,13 @@ export class OssBase implements OssBaseOperation {
290
325
  const response = await this.client.send(command);
291
326
 
292
327
  return {
328
+ standardHeaders: {
329
+ contentType: response.ContentType,
330
+ cacheControl: response.CacheControl,
331
+ contentDisposition: response.ContentDisposition,
332
+ contentEncoding: response.ContentEncoding,
333
+ contentLanguage: response.ContentLanguage,
334
+ },
293
335
  size: response.ContentLength || 0,
294
336
  etag: response.ETag?.replace?.(/"/g, '') || '',
295
337
  lastModified: response.LastModified || new Date(),
@@ -297,7 +339,6 @@ export class OssBase implements OssBaseOperation {
297
339
  versionId: response.VersionId || null,
298
340
  };
299
341
  } catch (e: any) {
300
- console.error('statObject error', e);
301
342
  // 检查是否是 404 错误 - 支持多种 S3 兼容存储的错误格式
302
343
  const isNotFound =
303
344
  e.name === 'NotFound' ||
@@ -311,6 +352,7 @@ export class OssBase implements OssBaseOperation {
311
352
  if (checkFile && isNotFound) {
312
353
  return null;
313
354
  }
355
+ console.error('statObject error', e);
314
356
  throw e;
315
357
  }
316
358
  }
@@ -438,4 +480,11 @@ export class OssBase implements OssBaseOperation {
438
480
  ...opts,
439
481
  });
440
482
  }
483
+ }
484
+
485
+ export const getStram = (data: GetObjectCommandOutput) => {
486
+ if (data.Body) {
487
+ return data.Body as Readable;
488
+ }
489
+ throw new Error('Object body is empty');
441
490
  }
package/src/s3/type.ts CHANGED
@@ -17,6 +17,13 @@ export type StatObjectResult = {
17
17
  lastModified: Date;
18
18
  metaData: ItemBucketMetadata;
19
19
  versionId?: string | null;
20
+ standardHeaders: {
21
+ contentType?: string;
22
+ cacheControl?: string;
23
+ contentDisposition?: string;
24
+ contentEncoding?: string;
25
+ contentLanguage?: string;
26
+ }
20
27
  };
21
28
 
22
29
  export type ListFileObject = {
@@ -24,6 +31,7 @@ export type ListFileObject = {
24
31
  size: number;
25
32
  lastModified: Date;
26
33
  etag: string;
34
+ metaData?: ItemBucketMetadata;
27
35
  };
28
36
 
29
37
  export type ListDirectoryObject = {
@@ -6,4 +6,4 @@ export * from '../util/download.ts';
6
6
 
7
7
  export * from '../util/index.ts';
8
8
 
9
- export * from '../core/type.ts';
9
+ export * from '../s3/type.ts';
@@ -1,73 +1,73 @@
1
- import { ServerResponse } from 'node:http';
2
- import { BucketItemStat } from 'minio';
3
- import fs from 'node:fs';
4
- import path from 'node:path';
1
+ // import { ServerResponse } from 'node:http';
2
+ // import { BucketItemStat } from 'minio';
3
+ // import fs from 'node:fs';
4
+ // import path from 'node:path';
5
5
 
6
- const viewableExtensions = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'mp4', 'webm', 'mp3', 'wav', 'ogg', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'];
7
- import { OssBase } from '../index.ts';
8
- /**
9
- * 过滤 metaData 中的 key, 去除 password, accesskey, secretkey,
10
- * 并返回过滤后的 metaData
11
- * @param metaData
12
- * @returns
13
- */
14
- export const filterMetaDataKeys = (metaData: Record<string, string>, clearKeys: string[] = []) => {
15
- const keys = Object.keys(metaData);
16
- // remove X-Amz- meta data
17
- const removeKeys = ['password', 'accesskey', 'secretkey', ...clearKeys];
18
- const filteredKeys = keys.filter((key) => !removeKeys.includes(key));
19
- return filteredKeys.reduce((acc, key) => {
20
- acc[key] = metaData[key];
21
- return acc;
22
- }, {} as Record<string, string>);
23
- };
24
- type SendObjectOptions = {
25
- res: ServerResponse;
26
- client: OssBase;
27
- objectName: string;
28
- isDownload?: boolean;
29
- };
30
- export const NotFoundFile = (res: ServerResponse, msg?: string, code = 404) => {
31
- res.writeHead(code, { 'Content-Type': 'text/plain' });
32
- res.end(msg || 'Not Found File');
33
- return;
34
- };
35
- export const sendObject = async ({ res, objectName, client, isDownload = false }: SendObjectOptions) => {
36
- let stat: BucketItemStat;
37
- try {
38
- stat = await client.statObject(objectName);
39
- } catch (e) {
40
- } finally {
41
- if (!stat || stat.size === 0) {
42
- return NotFoundFile(res);
43
- }
44
- const contentLength = stat.size;
45
- const etag = stat.etag;
46
- const lastModified = stat.lastModified.toISOString();
47
- const filename = objectName.split('/').pop() || 'no-file-name-download'; // Extract filename from objectName
48
- const fileExtension = filename.split('.').pop()?.toLowerCase() || '';
49
- const filteredMetaData = filterMetaDataKeys(stat.metaData, ['size', 'etag', 'last-modified']);
50
- const contentDisposition = viewableExtensions.includes(fileExtension) && !isDownload ? 'inline' : `attachment; filename="${filename}"`;
6
+ // const viewableExtensions = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'mp4', 'webm', 'mp3', 'wav', 'ogg', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'];
7
+ // import { OssBase } from '../index.ts';
8
+ // /**
9
+ // * 过滤 metaData 中的 key, 去除 password, accesskey, secretkey,
10
+ // * 并返回过滤后的 metaData
11
+ // * @param metaData
12
+ // * @returns
13
+ // */
14
+ // export const filterMetaDataKeys = (metaData: Record<string, string>, clearKeys: string[] = []) => {
15
+ // const keys = Object.keys(metaData);
16
+ // // remove X-Amz- meta data
17
+ // const removeKeys = ['password', 'accesskey', 'secretkey', ...clearKeys];
18
+ // const filteredKeys = keys.filter((key) => !removeKeys.includes(key));
19
+ // return filteredKeys.reduce((acc, key) => {
20
+ // acc[key] = metaData[key];
21
+ // return acc;
22
+ // }, {} as Record<string, string>);
23
+ // };
24
+ // type SendObjectOptions = {
25
+ // res: ServerResponse;
26
+ // client: OssBase;
27
+ // objectName: string;
28
+ // isDownload?: boolean;
29
+ // };
30
+ // export const NotFoundFile = (res: ServerResponse, msg?: string, code = 404) => {
31
+ // res.writeHead(code, { 'Content-Type': 'text/plain' });
32
+ // res.end(msg || 'Not Found File');
33
+ // return;
34
+ // };
35
+ // export const sendObject = async ({ res, objectName, client, isDownload = false }: SendObjectOptions) => {
36
+ // let stat: BucketItemStat;
37
+ // try {
38
+ // stat = await client.statObject(objectName);
39
+ // } catch (e) {
40
+ // } finally {
41
+ // if (!stat || stat.size === 0) {
42
+ // return NotFoundFile(res);
43
+ // }
44
+ // const contentLength = stat.size;
45
+ // const etag = stat.etag;
46
+ // const lastModified = stat.lastModified.toISOString();
47
+ // const filename = objectName.split('/').pop() || 'no-file-name-download'; // Extract filename from objectName
48
+ // const fileExtension = filename.split('.').pop()?.toLowerCase() || '';
49
+ // const filteredMetaData = filterMetaDataKeys(stat.metaData, ['size', 'etag', 'last-modified']);
50
+ // const contentDisposition = viewableExtensions.includes(fileExtension) && !isDownload ? 'inline' : `attachment; filename="${filename}"`;
51
51
 
52
- res.writeHead(200, {
53
- 'Content-Length': contentLength,
54
- etag,
55
- 'last-modified': lastModified,
56
- 'Content-Disposition': contentDisposition,
57
- ...filteredMetaData,
58
- });
59
- const objectStream = await client.getObject(objectName);
52
+ // res.writeHead(200, {
53
+ // 'Content-Length': contentLength,
54
+ // etag,
55
+ // 'last-modified': lastModified,
56
+ // 'Content-Disposition': contentDisposition,
57
+ // ...filteredMetaData,
58
+ // });
59
+ // const objectStream = await client.getObject(objectName);
60
60
 
61
- objectStream.pipe(res, { end: true });
62
- }
63
- };
61
+ // objectStream.pipe(res, { end: true });
62
+ // }
63
+ // };
64
64
 
65
- export const downloadObject = async ({ objectName, client, filePath }: Pick<SendObjectOptions, 'objectName' | 'client'> & { filePath: string }) => {
66
- const objectStream = await client.getObject(objectName);
67
- const dir = path.dirname(filePath);
68
- if (!fs.existsSync(dir)) {
69
- fs.mkdirSync(dir, { recursive: true });
70
- }
71
- objectStream.pipe(fs.createWriteStream(filePath));
72
- return objectStream;
73
- };
65
+ // export const downloadObject = async ({ objectName, client, filePath }: Pick<SendObjectOptions, 'objectName' | 'client'> & { filePath: string }) => {
66
+ // const objectStream = await client.getObject(objectName);
67
+ // const dir = path.dirname(filePath);
68
+ // if (!fs.existsSync(dir)) {
69
+ // fs.mkdirSync(dir, { recursive: true });
70
+ // }
71
+ // objectStream.pipe(fs.createWriteStream(filePath));
72
+ // return objectStream;
73
+ // };
@@ -1,26 +0,0 @@
1
- import { Client, CopyDestinationOptions, CopySourceOptions } from 'minio';
2
-
3
- type CopyObjectOpts = {
4
- bucketName: string;
5
- newMetadata: Record<string, string>;
6
- objectName: string;
7
- client: Client;
8
- };
9
- /**
10
- * 复制对象 REPLACE 替换
11
- * @param param0
12
- * @returns
13
- */
14
- export const copyObject = async ({ bucketName, newMetadata, objectName, client }: CopyObjectOpts) => {
15
- const source = new CopySourceOptions({ Bucket: bucketName, Object: objectName });
16
- const stat = await client.statObject(bucketName, objectName);
17
- const sourceMetadata = stat.metaData;
18
- const destination = new CopyDestinationOptions({
19
- Bucket: bucketName,
20
- Object: objectName,
21
- UserMetadata: { ...sourceMetadata, ...newMetadata },
22
- MetadataDirective: 'REPLACE',
23
- });
24
- const copyResult = await client.copyObject(source, destination);
25
- return copyResult;
26
- };