perf
This commit is contained in:
		
							
								
								
									
										18
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "@kevisual/oss", |   "name": "@kevisual/oss", | ||||||
|   "version": "0.0.1", |   "version": "0.0.5", | ||||||
|   "description": "", |   "description": "", | ||||||
|   "main": "dist/index.js", |   "main": "dist/index.js", | ||||||
|   "scripts": { |   "scripts": { | ||||||
| @@ -16,13 +16,23 @@ | |||||||
|   "license": "MIT", |   "license": "MIT", | ||||||
|   "type": "module", |   "type": "module", | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "dotenv": "^16.4.7", |     "dotenv": "^16.5.0", | ||||||
|     "minio": "^8.0.5", |     "minio": "^8.0.5", | ||||||
|     "tsup": "^8.4.0" |     "tsup": "^8.4.0" | ||||||
|   }, |   }, | ||||||
|   "exports": { |   "exports": { | ||||||
|     "./*": "./dist/*.js", |     ".": { | ||||||
|     "./services": "./dist/services/index.js" |       "import": "./dist/index.js", | ||||||
|  |       "types": "./dist/index.d.ts" | ||||||
|  |     }, | ||||||
|  |     "./config": { | ||||||
|  |       "import": "./dist/services/config.js", | ||||||
|  |       "types": "./dist/services/config.d.ts" | ||||||
|  |     }, | ||||||
|  |     "./services": { | ||||||
|  |       "import": "./dist/services/index.js", | ||||||
|  |       "types": "./dist/services/index.d.ts" | ||||||
|  |     } | ||||||
|   }, |   }, | ||||||
|   "publishConfig": { |   "publishConfig": { | ||||||
|     "access": "public" |     "access": "public" | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import { Client, CopyDestinationOptions, CopySourceOptions } from 'minio'; | |||||||
| type CopyObjectOpts = { | type CopyObjectOpts = { | ||||||
|   bucketName: string; |   bucketName: string; | ||||||
|   newMetadata: Record<string, string>; |   newMetadata: Record<string, string>; | ||||||
|   prefix: string; |   objectName: string; | ||||||
|   client: Client; |   client: Client; | ||||||
| }; | }; | ||||||
| /** | /** | ||||||
| @@ -11,12 +11,14 @@ type CopyObjectOpts = { | |||||||
|  * @param param0 |  * @param param0 | ||||||
|  * @returns |  * @returns | ||||||
|  */ |  */ | ||||||
| export const copyObject = async ({ bucketName, newMetadata, prefix, client }: CopyObjectOpts) => { | export const copyObject = async ({ bucketName, newMetadata, objectName, client }: CopyObjectOpts) => { | ||||||
|   const source = new CopySourceOptions({ Bucket: bucketName, Object: prefix }); |   const source = new CopySourceOptions({ Bucket: bucketName, Object: objectName }); | ||||||
|  |   const stat = await client.statObject(bucketName, objectName); | ||||||
|  |   const sourceMetadata = stat.metaData; | ||||||
|   const destination = new CopyDestinationOptions({ |   const destination = new CopyDestinationOptions({ | ||||||
|     Bucket: bucketName, |     Bucket: bucketName, | ||||||
|     Object: prefix, |     Object: objectName, | ||||||
|     UserMetadata: newMetadata, |     UserMetadata: { ...sourceMetadata, ...newMetadata }, | ||||||
|     MetadataDirective: 'REPLACE', |     MetadataDirective: 'REPLACE', | ||||||
|   }); |   }); | ||||||
|   const copyResult = await client.copyObject(source, destination); |   const copyResult = await client.copyObject(source, destination); | ||||||
|   | |||||||
							
								
								
									
										55
									
								
								src/index.ts
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								src/index.ts
									
									
									
									
									
								
							| @@ -1,12 +1,13 @@ | |||||||
| import { Client, ItemBucketMetadata } from 'minio'; | import { Client, ItemBucketMetadata } from 'minio'; | ||||||
| import { ListFileObject, ListObjectResult, OssBaseOperation } from './core/type.ts'; | import { ListFileObject, ListObjectResult, OssBaseOperation } from './core/type.ts'; | ||||||
| import { hash } from './util/hash.ts'; | import { hash } from './util/hash.ts'; | ||||||
|  | import { copyObject } from './core/copy-object.ts'; | ||||||
|  |  | ||||||
| export type OssBaseOptions<T = { [key: string]: any }> = { | export type OssBaseOptions<T = { [key: string]: any }> = { | ||||||
|   /** |   /** | ||||||
|    * 已经初始化好的minio client |    * 已经初始化好的minio client | ||||||
|    */ |    */ | ||||||
|   client?: Client; |   client: Client; | ||||||
|   /** |   /** | ||||||
|    * 桶名 |    * 桶名 | ||||||
|    */ |    */ | ||||||
| @@ -31,7 +32,7 @@ export class OssBase implements OssBaseOperation { | |||||||
|     } |     } | ||||||
|     this.bucketName = opts.bucketName; |     this.bucketName = opts.bucketName; | ||||||
|     this.client = opts.client; |     this.client = opts.client; | ||||||
|     this.prefix = opts.prefix; |     this.prefix = opts?.prefix ?? ''; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   setPrefix(prefix: string) { |   setPrefix(prefix: string) { | ||||||
| @@ -64,15 +65,36 @@ export class OssBase implements OssBaseOperation { | |||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  |   /** | ||||||
|   async putObject(objectName: string, data: Buffer | string | Object, metaData?: ItemBucketMetadata) { |    * 上传文件, | ||||||
|  |    * @param objectName | ||||||
|  |    * @param data | ||||||
|  |    * @param metaData | ||||||
|  |    * @param options 如果文件本身存在,则复制原有的meta的内容 | ||||||
|  |    * @returns | ||||||
|  |    */ | ||||||
|  |   async putObject(objectName: string, data: Buffer | string | Object, metaData: ItemBucketMetadata = {}, options?: { check?: boolean }) { | ||||||
|     let putData: Buffer | string; |     let putData: Buffer | string; | ||||||
|  |     let size: number; | ||||||
|     if (typeof data === 'object') { |     if (typeof data === 'object') { | ||||||
|       putData = JSON.stringify(data); |       putData = JSON.stringify(data); | ||||||
|  |       size = putData.length; | ||||||
|  |     } else if (typeof data === 'string') { | ||||||
|  |       putData = data; | ||||||
|  |       size = putData.length; | ||||||
|     } else { |     } else { | ||||||
|       putData = data; |       putData = data; | ||||||
|     } |     } | ||||||
|     const size = putData.length; |     if (options?.check) { | ||||||
|  |       const obj = await this.statObject(objectName, true); | ||||||
|  |       if (obj) { | ||||||
|  |         metaData = { | ||||||
|  |           ...obj.metaData, | ||||||
|  |           ...metaData, | ||||||
|  |         }; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     const bucketName = this.bucketName; |     const bucketName = this.bucketName; | ||||||
|     const obj = await this.client.putObject(bucketName, `${this.prefix}${objectName}`, putData, size, metaData); |     const obj = await this.client.putObject(bucketName, `${this.prefix}${objectName}`, putData, size, metaData); | ||||||
|     return obj; |     return obj; | ||||||
| @@ -117,10 +139,13 @@ export class OssBase implements OssBaseOperation { | |||||||
|     return obj as any; |     return obj as any; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async statObject(objectName: string) { |   async statObject(objectName: string, checkFile = true) { | ||||||
|     const bucketName = this.bucketName; |     const bucketName = this.bucketName; | ||||||
|     try { |     try { | ||||||
|       const obj = await this.client.statObject(bucketName, `${this.prefix}${objectName}`); |       const obj = await this.client.statObject(bucketName, `${this.prefix}${objectName}`); | ||||||
|  |       if (obj && checkFile && obj.size === 0) { | ||||||
|  |         return null; | ||||||
|  |       } | ||||||
|       return obj; |       return obj; | ||||||
|     } catch (e) { |     } catch (e) { | ||||||
|       if (e.code === 'NotFound') { |       if (e.code === 'NotFound') { | ||||||
| @@ -129,13 +154,29 @@ export class OssBase implements OssBaseOperation { | |||||||
|       throw e; |       throw e; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   /** | ||||||
|  |    * 检查文件hash是否一致 | ||||||
|  |    * @param objectName | ||||||
|  |    * @param hash | ||||||
|  |    * @returns | ||||||
|  |    */ | ||||||
|  |   async checkObjectHash(objectName: string, hash: string) { | ||||||
|  |     const obj = await this.statObject(`${this.prefix}${objectName}`, true); | ||||||
|  |     if (!obj) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |     return obj.etag === hash; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   async copyObject(sourceObject: any, targetObject: any) { |   async copyObject(sourceObject: any, targetObject: any) { | ||||||
|     const bucketName = this.bucketName; |     const bucketName = this.bucketName; | ||||||
|     const obj = await this.client.copyObject(bucketName, sourceObject, targetObject); |     const obj = await this.client.copyObject(bucketName, sourceObject, targetObject); | ||||||
|     return obj; |     return obj; | ||||||
|   } |   } | ||||||
|  |   async replaceObject(objectName: string, meta: { [key: string]: string }) { | ||||||
|  |     const { bucketName, client } = this; | ||||||
|  |     return copyObject({ bucketName, client, objectName: `${this.prefix}${objectName}`, newMetadata: meta }); | ||||||
|  |   } | ||||||
|   static create<T extends OssBase, U>(this: new (opts: OssBaseOptions<U>) => T, opts: OssBaseOptions<U>): T { |   static create<T extends OssBase, U>(this: new (opts: OssBaseOptions<U>) => T, opts: OssBaseOptions<U>): T { | ||||||
|     return new this(opts); |     return new this(opts); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,2 +1,9 @@ | |||||||
| export { OssBase, OssBaseOptions } from '../index.ts'; | export { OssBase } from '../index.ts'; | ||||||
|  | export type { OssBaseOptions } from '../index.ts'; | ||||||
| export { ConfigOssService } from './config.ts'; | export { ConfigOssService } from './config.ts'; | ||||||
|  |  | ||||||
|  | export * from '../util/download.ts'; | ||||||
|  |  | ||||||
|  | export * from '../util/index.ts'; | ||||||
|  |  | ||||||
|  | export * from '../core/type.ts'; | ||||||
|   | |||||||
| @@ -4,9 +4,16 @@ import { Client } from 'minio'; | |||||||
| import path from 'path'; | import path from 'path'; | ||||||
| import { downloadObject } from '../util/download.ts'; | import { downloadObject } from '../util/download.ts'; | ||||||
| const cwd = process.cwd(); | const cwd = process.cwd(); | ||||||
| dotenv.config({ path: path.resolve(cwd, '..', '..', '.env') }); | dotenv.config({ path: path.resolve(cwd, '..', '..', '.env.dev') }); | ||||||
|  |  | ||||||
| console.log(process.env.MINIO_ENDPOINT, process.env.MINIO_USE_SSL, process.env.MINIO_ACCESS_KEY, process.env.MINIO_SECRET_KEY, process.env.MINIO_BUCKET_NAME); | console.log( | ||||||
|  |   'config', | ||||||
|  |   process.env.MINIO_ENDPOINT, | ||||||
|  |   process.env.MINIO_USE_SSL, | ||||||
|  |   process.env.MINIO_ACCESS_KEY, | ||||||
|  |   process.env.MINIO_SECRET_KEY, | ||||||
|  |   process.env.MINIO_BUCKET_NAME, | ||||||
|  | ); | ||||||
| const client = new Client({ | const client = new Client({ | ||||||
|   endPoint: process.env.MINIO_ENDPOINT, |   endPoint: process.env.MINIO_ENDPOINT, | ||||||
|   useSSL: process.env.MINIO_USE_SSL === 'true', |   useSSL: process.env.MINIO_USE_SSL === 'true', | ||||||
| @@ -25,7 +32,7 @@ const main = async () => { | |||||||
|   console.log(config); |   console.log(config); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // main(); | main(); | ||||||
| const putJson = async () => { | const putJson = async () => { | ||||||
|   const config = await configOssService.putObject( |   const config = await configOssService.putObject( | ||||||
|     'a.json', |     'a.json', | ||||||
| @@ -50,7 +57,7 @@ const downloadMain = async () => { | |||||||
|   }); |   }); | ||||||
|   // console.log(objectStream); |   // console.log(objectStream); | ||||||
| }; | }; | ||||||
| downloadMain(); | // downloadMain(); | ||||||
|  |  | ||||||
| const statInfo = async () => { | const statInfo = async () => { | ||||||
|   try { |   try { | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { ServerResponse } from 'http'; | import { ServerResponse } from 'node:http'; | ||||||
| import { BucketItemStat } from 'minio'; | import { BucketItemStat } from 'minio'; | ||||||
| import fs from 'fs'; | import fs from 'node:fs'; | ||||||
| import path from 'path'; | import path from 'node:path'; | ||||||
|  |  | ||||||
| const viewableExtensions = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'mp4', 'webm', 'mp3', 'wav', 'ogg', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx']; | const viewableExtensions = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'mp4', 'webm', 'mp3', 'wav', 'ogg', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx']; | ||||||
| import { OssBase } from '../index.ts'; | import { OssBase } from '../index.ts'; | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import crypto from 'crypto'; | import crypto from 'node:crypto'; | ||||||
| // 582af9ef5cdc53d6628f45cb842f874a | // 582af9ef5cdc53d6628f45cb842f874a | ||||||
| // const hashStr = '{"a":"a"}'; | // const hashStr = '{"a":"a"}'; | ||||||
| // const hash = crypto.createHash('md5').update(hashStr).digest('hex'); | // const hash = crypto.createHash('md5').update(hashStr).digest('hex'); | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ const services = glob.sync('src/services/*.ts'); | |||||||
|  |  | ||||||
| export default defineConfig({ | export default defineConfig({ | ||||||
|   entry: ['src/index.ts', ...services], |   entry: ['src/index.ts', ...services], | ||||||
|  |   target: 'node22', | ||||||
|   splitting: false, |   splitting: false, | ||||||
|   sourcemap: false, |   sourcemap: false, | ||||||
|   clean: true, |   clean: true, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user