From ab29a1eb0b4e71739238f33f25c5746db2bbe198 Mon Sep 17 00:00:00 2001 From: xion Date: Mon, 12 May 2025 17:37:30 +0800 Subject: [PATCH] update hash and put object --- package.json | 2 +- src/index.ts | 43 ++++++++++++++++++++++++++----- src/util/get-content-type.ts | 49 ++++++++++++++++++++++++++++++++++++ src/util/hash.ts | 4 ++- src/util/index.ts | 2 ++ 5 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 src/util/get-content-type.ts diff --git a/package.json b/package.json index c3ef547..92c5d1e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kevisual/oss", - "version": "0.0.10", + "version": "0.0.11", "main": "dist/index.js", "scripts": { "build": "tsup", diff --git a/src/index.ts b/src/index.ts index 188122e..93e8e65 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,6 +3,7 @@ import { ListFileObject, ListObjectResult, OssBaseOperation } from './core/type. import { hash } from './util/hash.ts'; import { copyObject } from './core/copy-object.ts'; import omit from 'lodash/omit.js'; +import { getContentType } from './util/get-content-type.ts'; export type OssBaseOptions = { /** * 已经初始化好的minio client @@ -66,7 +67,7 @@ export class OssBase implements OssBaseOperation { }); } /** - * 上传文件, + * 上传文件, 当是流的时候,中断之后的etag会变,所以传递的时候不要嵌套async await,例如 busboy 监听文件流内部的时候,不要用check * @param objectName * @param data * @param metaData @@ -99,7 +100,7 @@ export class OssBase implements OssBaseOperation { if (opts?.check) { const obj = await this.statObject(objectName, true); if (obj) { - const omitMeda = ['content-type', 'cache-control', 'app-source']; + const omitMeda = ['size', 'content-type', 'cache-control', 'app-source']; const objMeta = JSON.parse(JSON.stringify(omit(obj.metaData, omitMeda))); metaData = { ...objMeta, @@ -107,7 +108,6 @@ export class OssBase implements OssBaseOperation { }; } } - console.log('putObject metaData', metaData); const bucketName = this.bucketName; const obj = await this.client.putObject(bucketName, `${this.prefix}${objectName}`, putData, size, metaData); @@ -174,12 +174,43 @@ export class OssBase implements OssBaseOperation { * @param hash * @returns */ - async checkObjectHash(objectName: string, hash: string) { + async checkObjectHash( + objectName: string, + hash: string, + meta?: ItemBucketMetadata, + ): Promise<{ success: boolean; metaData: ItemBucketMetadata | null; obj: any; equalMeta?: boolean }> { const obj = await this.statObject(`${this.prefix}${objectName}`, true); if (!obj) { - return false; + return { success: false, metaData: null, obj: null, equalMeta: false }; } - return obj.etag === hash; + let metaData: ItemBucketMetadata = {}; + const omitMeda = ['content-type', 'cache-control', 'app-source']; + const objMeta = omit(obj.metaData, omitMeda); + metaData = { + ...objMeta, + }; + let equalMeta = false; + if (meta) { + equalMeta = JSON.stringify(metaData) === JSON.stringify(meta); + } + return { success: obj.etag === hash, metaData, obj, equalMeta }; + } + getMetadata(pathname: string, meta: ItemBucketMetadata = { 'app-source': 'user-app' }) { + const isHtml = pathname.endsWith('.html'); + if (isHtml) { + meta = { + ...meta, + 'content-type': 'text/html; charset=utf-8', + 'cache-control': 'no-cache', + }; + } else { + meta = { + ...meta, + 'content-type': getContentType(pathname), + 'cache-control': 'max-age=31536000, immutable', + }; + } + return meta; } async copyObject(sourceObject: any, targetObject: any) { diff --git a/src/util/get-content-type.ts b/src/util/get-content-type.ts new file mode 100644 index 0000000..08a31e6 --- /dev/null +++ b/src/util/get-content-type.ts @@ -0,0 +1,49 @@ +import path from 'node:path'; +// 获取文件的 content-type +export const getContentType = (filePath: string) => { + const extname = path.extname(filePath); + const contentType = { + '.html': 'text/html; charset=utf-8', + '.js': 'text/javascript; charset=utf-8', + '.css': 'text/css; charset=utf-8', + '.txt': 'text/plain; charset=utf-8', + '.json': 'application/json; charset=utf-8', + '.png': 'image/png', + '.jpg': 'image/jpg', + '.gif': 'image/gif', + '.svg': 'image/svg+xml', + '.wav': 'audio/wav', + '.mp4': 'video/mp4', + '.md': 'text/markdown; charset=utf-8', // utf-8配置 + '.ico': 'image/x-icon', // Favicon 图标 + '.webp': 'image/webp', // WebP 图像格式 + '.webm': 'video/webm', // WebM 视频格式 + '.ogg': 'audio/ogg', // Ogg 音频格式 + '.mp3': 'audio/mpeg', // MP3 音频格式 + '.m4a': 'audio/mp4', // M4A 音频格式 + '.m3u8': 'application/vnd.apple.mpegurl', // HLS 播放列表 + '.ts': 'video/mp2t', // MPEG Transport Stream + '.pdf': 'application/pdf', // PDF 文档 + '.doc': 'application/msword', // Word 文档 + '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // Word 文档 (新版) + '.ppt': 'application/vnd.ms-powerpoint', // PowerPoint 演示文稿 + '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // PowerPoint (新版) + '.xls': 'application/vnd.ms-excel', // Excel 表格 + '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // Excel 表格 (新版) + '.csv': 'text/csv; charset=utf-8', // CSV 文件 + '.xml': 'application/xml; charset=utf-8', // XML 文件 + '.rtf': 'application/rtf', // RTF 文本文件 + '.eot': 'application/vnd.ms-fontobject', // Embedded OpenType 字体 + '.ttf': 'font/ttf', // TrueType 字体 + '.woff': 'font/woff', // Web Open Font Format 1.0 + '.woff2': 'font/woff2', // Web Open Font Format 2.0 + '.otf': 'font/otf', // OpenType 字体 + '.wasm': 'application/wasm', // WebAssembly 文件 + '.pem': 'application/x-pem-file', // PEM 证书文件 + '.crt': 'application/x-x509-ca-cert', // CRT 证书文件 + '.yaml': 'application/x-yaml; charset=utf-8', // YAML 文件 + '.yml': 'application/x-yaml; charset=utf-8', // YAML 文件(别名) + '.zip': 'application/octet-stream', + }; + return contentType[extname] || 'application/octet-stream'; +}; diff --git a/src/util/hash.ts b/src/util/hash.ts index 55c8c6a..92a85fe 100644 --- a/src/util/hash.ts +++ b/src/util/hash.ts @@ -11,7 +11,9 @@ import crypto from 'node:crypto'; */ export const hash = (str: string | Buffer | Object) => { let hashStr: string | Buffer; - if (typeof str === 'object') { + if (str instanceof Buffer) { + hashStr = str; + } else if (str instanceof Object) { hashStr = JSON.stringify(str, null, 2); } else { hashStr = str; diff --git a/src/util/index.ts b/src/util/index.ts index 0f4b53d..327f57d 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -1 +1,3 @@ export * from './hash.ts'; + +export * from './get-content-type.ts';