@nest-boot/file-upload 6.3.2 → 7.0.0-beta.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.
@@ -1,9 +1,10 @@
1
- import { ClientOptions } from "minio";
1
+ import { S3Client, S3ClientConfig } from "@aws-sdk/client-s3";
2
2
  export interface FileUploadLimit {
3
3
  fileSize: number;
4
4
  mimeTypes: string[];
5
5
  }
6
- export interface FileUploadModuleOptions extends ClientOptions {
6
+ export interface FileUploadModuleOptions {
7
+ client: S3Client | S3ClientConfig;
7
8
  bucket: string;
8
9
  expires?: number;
9
10
  limits?: FileUploadLimit[];
@@ -1,16 +1,17 @@
1
- import { ItemBucketMetadata } from "minio";
2
1
  import { Readable } from "stream";
3
2
  import { FileUpload } from "./file-upload.object";
4
3
  import { FileUploadModuleOptions } from "./file-upload-options.interface";
5
4
  import { FileUploadInput } from "./inputs/file-upload.input";
6
5
  export declare class FileUploadService {
7
6
  private readonly options;
8
- private readonly client;
7
+ private readonly s3Client;
9
8
  constructor(options: FileUploadModuleOptions);
10
9
  create(input: FileUploadInput[]): Promise<FileUpload[]>;
11
10
  persist(tmpUrl: string): Promise<string>;
12
- upload(data: Readable | Buffer | string, metadata: ItemBucketMetadata & {
11
+ upload(data: Readable | Buffer | string, metadata: {
13
12
  "Content-Type": string;
13
+ extension?: string;
14
+ [key: string]: any;
14
15
  }, persist?: boolean): Promise<string>;
15
16
  private getFileUrl;
16
17
  }
@@ -16,17 +16,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
16
16
  };
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.FileUploadService = void 0;
19
+ const client_s3_1 = require("@aws-sdk/client-s3");
20
+ const s3_presigned_post_1 = require("@aws-sdk/s3-presigned-post");
19
21
  const common_1 = require("@nestjs/common");
20
22
  const crypto_1 = require("crypto");
21
23
  const dayjs_1 = __importDefault(require("dayjs"));
22
24
  const mime_types_1 = __importDefault(require("mime-types"));
23
- const minio_1 = require("minio");
24
25
  const path_1 = require("path");
25
26
  const file_upload_module_definition_1 = require("./file-upload.module-definition");
26
27
  let FileUploadService = class FileUploadService {
27
28
  constructor(options) {
28
29
  this.options = options;
29
- this.client = new minio_1.Client(options);
30
+ this.s3Client =
31
+ options.client instanceof client_s3_1.S3Client
32
+ ? options.client
33
+ : new client_s3_1.S3Client(options.client);
30
34
  }
31
35
  async create(input) {
32
36
  const results = input.map(async (item) => {
@@ -36,30 +40,28 @@ let FileUploadService = class FileUploadService {
36
40
  // 上传的文件不符合要求
37
41
  throw new common_1.BadRequestException("The uploaded file does not meet the requirements");
38
42
  }
39
- const policy = this.client.newPostPolicy();
40
- policy.formData = {
41
- bucket: this.options.bucket,
42
- key,
43
- success_action_status: "201",
44
- "Content-Type": item.mimeType,
45
- };
46
- policy.policy = {
47
- conditions: [
48
- ...(limit ? [["content-length-range", 1, limit.fileSize]] : []),
49
- ["eq", "$bucket", this.options.bucket],
50
- ["eq", "$key", key],
51
- ["eq", "$success_action_status", "201"],
52
- ["eq", "$Content-Type", item.mimeType],
53
- ],
54
- // 上传链接的过期时间,不是临时文件的过期时间
55
- expiration: new Date(Date.now() + (this.options.expires ?? 3600) * 1000).toISOString(),
56
- };
57
- const presignedPost = await this.client.presignedPostPolicy(policy);
43
+ const conditions = [
44
+ ...(limit ? [["content-length-range", 1, limit.fileSize]] : []),
45
+ ["eq", "$bucket", this.options.bucket],
46
+ ["eq", "$key", key],
47
+ ["eq", "$success_action_status", "201"],
48
+ ["eq", "$Content-Type", item.mimeType],
49
+ ];
50
+ const presignedPost = await (0, s3_presigned_post_1.createPresignedPost)(this.s3Client, {
51
+ Bucket: this.options.bucket,
52
+ Key: key,
53
+ Conditions: conditions,
54
+ Fields: {
55
+ success_action_status: "201",
56
+ "Content-Type": item.mimeType,
57
+ },
58
+ Expires: this.options.expires ?? 3600,
59
+ });
58
60
  return {
59
- url: presignedPost.postURL,
61
+ url: presignedPost.url,
60
62
  fields: [
61
- { name: "key", value: presignedPost.formData.key },
62
- ...Object.entries(presignedPost.formData)
63
+ { name: "key", value: presignedPost.fields.key },
64
+ ...Object.entries(presignedPost.fields)
63
65
  .filter(([name]) => name !== "key")
64
66
  .map(([name, value]) => ({
65
67
  name,
@@ -72,27 +74,57 @@ let FileUploadService = class FileUploadService {
72
74
  }
73
75
  // 临时文件转永久文件
74
76
  async persist(tmpUrl) {
75
- const originPath = `${this.options.bucket}/tmp/${tmpUrl.split("/tmp/")[1]}`;
76
- const targetPath = `files/${(0, dayjs_1.default)().format("YYYY/MM/DD")}/${String(originPath.split("/").pop())}`;
77
- const conditions = new minio_1.CopyConditions();
78
- await this.client.copyObject(this.options.bucket, targetPath, originPath, conditions);
79
- return this.getFileUrl(targetPath);
77
+ const tmpKey = tmpUrl.split("/tmp/")[1];
78
+ const originKey = `tmp/${tmpKey}`;
79
+ const targetKey = `files/${(0, dayjs_1.default)().format("YYYY/MM/DD")}/${tmpKey}`;
80
+ const copyCommand = new client_s3_1.CopyObjectCommand({
81
+ Bucket: this.options.bucket,
82
+ CopySource: `${this.options.bucket}/${originKey}`,
83
+ Key: targetKey,
84
+ });
85
+ await this.s3Client.send(copyCommand);
86
+ return await this.getFileUrl(targetKey);
80
87
  }
81
88
  async upload(data, metadata, persist = false) {
82
- const extension = metadata.extension || mime_types_1.default.extension(metadata["Content-Type"]);
89
+ const extension = metadata.extension ??
90
+ (mime_types_1.default.extension(metadata["Content-Type"]) || "bin");
83
91
  const filePath = `tmp/${(0, dayjs_1.default)().format("YYYY/MM/DD")}/${(0, crypto_1.randomUUID)()}.${extension}`;
84
- await this.client.putObject(this.options.bucket, filePath, data, undefined, metadata);
85
- const tmpUrl = this.getFileUrl(filePath);
92
+ await this.s3Client.send(new client_s3_1.PutObjectCommand({
93
+ Bucket: this.options.bucket,
94
+ Key: filePath,
95
+ Body: data,
96
+ ContentType: metadata["Content-Type"],
97
+ Metadata: metadata,
98
+ }));
99
+ const tmpUrl = await this.getFileUrl(filePath);
86
100
  if (!persist) {
87
101
  return tmpUrl;
88
102
  }
89
103
  // 持久化
90
104
  return await this.persist(tmpUrl);
91
105
  }
92
- getFileUrl(filePath) {
93
- return this.options.pathStyle
94
- ? `${this.options.useSSL !== false ? "https" : "http"}://${this.options.endPoint}${this.options.port ? `:${String(this.options.port)}` : ""}/${this.options.bucket}/${filePath}`
95
- : `${this.options.useSSL !== false ? "https" : "http"}://${this.options.bucket}.${this.options.endPoint}${this.options.port ? `:${String(this.options.port)}` : ""}/${filePath}`;
106
+ async getFileUrl(filePath) {
107
+ // 获取 S3Client 的配置
108
+ const config = this.s3Client.config;
109
+ const forcePathStyle = config.forcePathStyle;
110
+ const endpoint = await config.endpoint?.();
111
+ if (!endpoint) {
112
+ throw new Error("Endpoint is not configured");
113
+ }
114
+ // 构造基础 URL
115
+ const protocol = String(endpoint.protocol);
116
+ const hostname = String(endpoint.hostname);
117
+ const port = endpoint.port ? `:${String(endpoint.port)}` : "";
118
+ const baseUrl = `${protocol}//${hostname}${port}`;
119
+ // 根据配置生成正确的 URL
120
+ if (forcePathStyle) {
121
+ // Path-style URL: https://endpoint/bucket/key
122
+ return `${baseUrl}/${this.options.bucket}/${filePath}`;
123
+ }
124
+ else {
125
+ // Virtual-hosted-style URL: https://bucket.endpoint/key
126
+ return `${protocol}//${this.options.bucket}.${hostname}${port}/${filePath}`;
127
+ }
96
128
  }
97
129
  };
98
130
  exports.FileUploadService = FileUploadService;
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload.service.js","sourceRoot":"","sources":["../src/file-upload.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-upload.service.js","sourceRoot":"","sources":["../src/file-upload.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,kDAI4B;AAC5B,kEAAiE;AACjE,2CAAyE;AACzE,mCAAoC;AACpC,kDAA0B;AAC1B,4DAAmC;AACnC,+BAA+B;AAG/B,mFAAuE;AAMhE,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAG5B,YAEmB,OAAgC;QAAhC,YAAO,GAAP,OAAO,CAAyB;QAEjD,IAAI,CAAC,QAAQ;YACX,OAAO,CAAC,MAAM,YAAY,oBAAQ;gBAChC,CAAC,CAAC,OAAO,CAAC,MAAM;gBAChB,CAAC,CAAC,IAAI,oBAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAwB;QACnC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YACvC,MAAM,GAAG,GAAG,OAAO,IAAA,mBAAU,GAAE,GAAG,IAAA,cAAO,EAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAEvD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CACrC,CAAC,CAAC,EAAE,EAAE,CACJ,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CACrE,CAAC;YAEF,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;gBAClC,aAAa;gBACb,MAAM,IAAI,4BAAmB,CAC3B,kDAAkD,CACnD,CAAC;YACJ,CAAC;YAED,MAAM,UAAU,GAAU;gBACxB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,EAAE,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/D,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;gBACtC,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC;gBACnB,CAAC,IAAI,EAAE,wBAAwB,EAAE,KAAK,CAAC;gBACvC,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC;aACvC,CAAC;YAEF,MAAM,aAAa,GAAG,MAAM,IAAA,uCAAmB,EAAC,IAAI,CAAC,QAAQ,EAAE;gBAC7D,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;gBAC3B,GAAG,EAAE,GAAG;gBACR,UAAU,EAAE,UAAiB;gBAC7B,MAAM,EAAE;oBACN,qBAAqB,EAAE,KAAK;oBAC5B,cAAc,EAAE,IAAI,CAAC,QAAQ;iBAC9B;gBACD,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI;aACtC,CAAC,CAAC;YAEH,OAAO;gBACL,GAAG,EAAE,aAAa,CAAC,GAAG;gBACtB,MAAM,EAAE;oBACN,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,EAAE;oBAChD,GAAG,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC;yBACpC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,KAAK,CAAC;yBAClC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;wBACvB,IAAI;wBACJ,KAAK;qBACN,CAAC,CAAC;iBACN;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,YAAY;IACZ,KAAK,CAAC,OAAO,CAAC,MAAc;QAC1B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,OAAO,MAAM,EAAE,CAAC;QAElC,MAAM,SAAS,GAAG,SAAS,IAAA,eAAK,GAAE,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,MAAM,EAAE,CAAC;QAEpE,MAAM,WAAW,GAAG,IAAI,6BAAiB,CAAC;YACxC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC3B,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,SAAS,EAAE;YACjD,GAAG,EAAE,SAAS;SACf,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAEtC,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,MAAM,CACV,IAAgC,EAChC,QAIC,EACD,OAAO,GAAG,KAAK;QAEf,MAAM,SAAS,GACb,QAAQ,CAAC,SAAS;YAClB,CAAC,oBAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC;QAE3D,MAAM,QAAQ,GAAG,OAAO,IAAA,eAAK,GAAE,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,IAAA,mBAAU,GAAE,IAAI,SAAS,EAAE,CAAC;QAEpF,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CACtB,IAAI,4BAAgB,CAAC;YACnB,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC3B,GAAG,EAAE,QAAQ;YACb,IAAI,EAAE,IAAI;YACV,WAAW,EAAE,QAAQ,CAAC,cAAc,CAAC;YACrC,QAAQ,EAAE,QAAQ;SACnB,CAAC,CACH,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAE/C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM;QACN,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,QAAgB;QACvC,kBAAkB;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACpC,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QAC7C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;QAE3C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QAED,WAAW;QACX,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,MAAM,OAAO,GAAG,GAAG,QAAQ,KAAK,QAAQ,GAAG,IAAI,EAAE,CAAC;QAElD,gBAAgB;QAChB,IAAI,cAAc,EAAE,CAAC;YACnB,8CAA8C;YAC9C,OAAO,GAAG,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;QACzD,CAAC;aAAM,CAAC;YACN,wDAAwD;YACxD,OAAO,GAAG,QAAQ,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,QAAQ,GAAG,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC9E,CAAC;IACH,CAAC;CACF,CAAA;AA/IY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;IAKR,WAAA,IAAA,eAAM,EAAC,oDAAoB,CAAC,CAAA;;GAJpB,iBAAiB,CA+I7B"}