@kevisual/oss 0.0.12 → 0.0.14
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/index.d.ts +162 -4
- package/dist/index.js +25 -2395
- package/dist/services/config.d.ts +187 -29
- package/dist/services/config.js +52 -2401
- package/dist/services/index.d.ts +220 -23
- package/dist/services/index.js +63 -2413
- package/package.json +14 -9
- package/src/core/copy-object.ts +26 -0
- package/src/core/type.ts +87 -0
- package/src/index.ts +244 -0
- package/src/s3/copy-object.ts +46 -0
- package/src/s3/core.ts +425 -0
- package/src/s3/type.ts +157 -0
- package/src/services/config.ts +67 -0
- package/src/services/index.ts +9 -0
- package/src/test/common.ts +103 -0
- package/src/test/config-admin.ts +84 -0
- package/src/test/test-s3.ts +23 -0
- package/src/util/download.ts +73 -0
- package/src/util/extract-standard-headers.ts +44 -0
- package/src/util/get-content-type.ts +49 -0
- package/src/util/hash.ts +26 -0
- package/src/util/index.ts +5 -0
- package/dist/index-BGsBfWH-.d.ts +0 -161
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as dotenv from 'dotenv';
|
|
2
|
+
dotenv.config();
|
|
3
|
+
|
|
4
|
+
import { S3Client, ListObjectsV2Command, GetBucketMetadataConfigurationCommand, HeadObjectCommand, CopyObjectCommand } from '@aws-sdk/client-s3';
|
|
5
|
+
|
|
6
|
+
export const s3Client = new S3Client({
|
|
7
|
+
credentials: {
|
|
8
|
+
accessKeyId: process.env.S3_ACCESS_KEY_ID || '',
|
|
9
|
+
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY || '',
|
|
10
|
+
},
|
|
11
|
+
region: process.env.S3_REGION,
|
|
12
|
+
endpoint: 'https://tos-s3-cn-shanghai.volces.com',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const bucketName = process.env.S3_BUCKET_NAME;
|
|
16
|
+
|
|
17
|
+
export async function listS3Objects() {
|
|
18
|
+
const command = new ListObjectsV2Command({
|
|
19
|
+
Bucket: process.env.S3_BUCKET_NAME,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const result = await s3Client.send(command);
|
|
24
|
+
console.log('S3 Objects:', result.Contents);
|
|
25
|
+
return result.Contents;
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error('Error listing S3 objects:', error);
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// listS3Objects();
|
|
33
|
+
|
|
34
|
+
export async function getMetaData(key = 'readme.md') {
|
|
35
|
+
const command = new HeadObjectCommand({
|
|
36
|
+
Bucket: process.env.S3_BUCKET_NAME,
|
|
37
|
+
Key: key,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const result = await s3Client.send(command);
|
|
42
|
+
// 解码 TOS 返回的 URL 编码的元数据值
|
|
43
|
+
const decodedMetadata: Record<string, string> = {};
|
|
44
|
+
if (result.Metadata) {
|
|
45
|
+
for (const [key, value] of Object.entries(result.Metadata)) {
|
|
46
|
+
decodedMetadata[key] = decodeURIComponent(value);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
console.log('Metadata for', result);
|
|
50
|
+
|
|
51
|
+
return decodedMetadata;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error('Error getting metadata for', key, ':', error);
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// const metadata = await getMetaData();
|
|
59
|
+
// console.log('metadata', metadata);
|
|
60
|
+
|
|
61
|
+
export async function setMetaData(key = 'readme.md', metadata: Record<string, string>) {
|
|
62
|
+
// 注意:S3 不支持直接更新对象的元数据。必须通过复制对象到自身来实现元数据的更新。
|
|
63
|
+
const copySource = `${process.env.S3_BUCKET_NAME}/${key}`;
|
|
64
|
+
|
|
65
|
+
// 分离标准 HTTP 头和自定义元数据
|
|
66
|
+
// 标准头应作为顶层参数,自定义元数据才放在 Metadata 中
|
|
67
|
+
const standardHeaders: Record<string, any> = {};
|
|
68
|
+
const customMetadata: Record<string, string> = {};
|
|
69
|
+
|
|
70
|
+
const standardHeaderKeys = ['content-type', 'cache-control', 'content-disposition', 'content-encoding', 'content-language', 'expires'];
|
|
71
|
+
|
|
72
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
73
|
+
const lowerKey = key.toLowerCase();
|
|
74
|
+
if (standardHeaderKeys.includes(lowerKey)) {
|
|
75
|
+
// 使用驼峰命名
|
|
76
|
+
const camelKey = lowerKey.split('-').map((word, index) =>
|
|
77
|
+
index === 0 ? word.charAt(0).toUpperCase() + word.slice(1) : word.charAt(0).toUpperCase() + word.slice(1)
|
|
78
|
+
).join('');
|
|
79
|
+
standardHeaders[camelKey] = value;
|
|
80
|
+
} else {
|
|
81
|
+
customMetadata[key] = value;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const command = new CopyObjectCommand({
|
|
86
|
+
Bucket: process.env.S3_BUCKET_NAME,
|
|
87
|
+
Key: key,
|
|
88
|
+
CopySource: copySource,
|
|
89
|
+
...standardHeaders, // 标准头作为顶层参数
|
|
90
|
+
Metadata: customMetadata, // 只有自定义元数据放在这里
|
|
91
|
+
MetadataDirective: 'REPLACE', // 指定替换元数据
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const result = await s3Client.send(command);
|
|
96
|
+
console.log('Metadata updated successfully for', key);
|
|
97
|
+
return result;
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.error('Error setting metadata for', key, ':', error);
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// setMetaData('readme.md', { 'type': 'app', 'Content-Type': 'text/html' });
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { config } from 'dotenv';
|
|
2
|
+
import { ConfigOssService } from '../services/index.ts';
|
|
3
|
+
import { Client } from 'minio';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { downloadObject } from '../util/download.ts';
|
|
6
|
+
const cwd = process.cwd();
|
|
7
|
+
config({ path: path.resolve(cwd, '..', '..', '.env.dev') });
|
|
8
|
+
|
|
9
|
+
console.log(
|
|
10
|
+
'config',
|
|
11
|
+
process.env.MINIO_ENDPOINT,
|
|
12
|
+
process.env.MINIO_USE_SSL,
|
|
13
|
+
process.env.MINIO_ACCESS_KEY,
|
|
14
|
+
process.env.MINIO_SECRET_KEY,
|
|
15
|
+
process.env.MINIO_BUCKET_NAME,
|
|
16
|
+
);
|
|
17
|
+
const client = new Client({
|
|
18
|
+
endPoint: process.env.MINIO_ENDPOINT,
|
|
19
|
+
useSSL: process.env.MINIO_USE_SSL === 'true',
|
|
20
|
+
accessKey: process.env.MINIO_ACCESS_KEY,
|
|
21
|
+
secretKey: process.env.MINIO_SECRET_KEY,
|
|
22
|
+
});
|
|
23
|
+
const configOssService = new ConfigOssService({
|
|
24
|
+
client,
|
|
25
|
+
bucketName: process.env.MINIO_BUCKET_NAME,
|
|
26
|
+
owner: 'admin',
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const main = async () => {
|
|
30
|
+
configOssService.setPrefix('root');
|
|
31
|
+
const config = await configOssService.statObject('avatar.png');
|
|
32
|
+
console.log(config);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
main();
|
|
36
|
+
const putJson = async () => {
|
|
37
|
+
const config = await configOssService.putObject(
|
|
38
|
+
'a.json',
|
|
39
|
+
{
|
|
40
|
+
a: 'a',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
'content-type': 'application/json',
|
|
44
|
+
'cache-control': 'no-cache',
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
console.log(config);
|
|
48
|
+
};
|
|
49
|
+
// putJson();
|
|
50
|
+
const downloadMain = async () => {
|
|
51
|
+
const stat = await configOssService.statObject('a.json'); // 582af9ef5cdc53d6628f45cb842f874a
|
|
52
|
+
console.log(stat);
|
|
53
|
+
const objectStream = await downloadObject({
|
|
54
|
+
objectName: 'a.json',
|
|
55
|
+
client: configOssService,
|
|
56
|
+
filePath: path.resolve(cwd, 'a.json'),
|
|
57
|
+
});
|
|
58
|
+
// console.log(objectStream);
|
|
59
|
+
};
|
|
60
|
+
// downloadMain();
|
|
61
|
+
|
|
62
|
+
const statInfo = async () => {
|
|
63
|
+
try {
|
|
64
|
+
const stat = await configOssService.statObject('a.json');
|
|
65
|
+
// configOssService.setPrefix('root/');
|
|
66
|
+
// const stat = await configOssService.statObject('avatar.png');
|
|
67
|
+
// const stat = await configOssService.statObject('center/0.0.1/index.html');
|
|
68
|
+
console.log(stat);
|
|
69
|
+
} catch (e) {
|
|
70
|
+
if (e.code === 'NotFound') {
|
|
71
|
+
console.log('not found');
|
|
72
|
+
} else {
|
|
73
|
+
console.log('error', e);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
// statInfo();
|
|
78
|
+
|
|
79
|
+
const listObjects = async () => {
|
|
80
|
+
configOssService.setPrefix('root/avatar.png');
|
|
81
|
+
const list = await configOssService.listObjects('');
|
|
82
|
+
console.log(list);
|
|
83
|
+
};
|
|
84
|
+
// listObjects();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { OssBase } from "@/s3/core.ts";
|
|
2
|
+
|
|
3
|
+
import { s3Client, bucketName } from './common.ts';
|
|
4
|
+
|
|
5
|
+
const oss = new OssBase({
|
|
6
|
+
client: s3Client,
|
|
7
|
+
bucketName: bucketName,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
// const list = await oss.listObjects('');
|
|
11
|
+
|
|
12
|
+
// console.log(list);
|
|
13
|
+
|
|
14
|
+
// const obj = await oss.getObjectAsString('readme.md');
|
|
15
|
+
// console.log(obj);
|
|
16
|
+
|
|
17
|
+
let putJson = {
|
|
18
|
+
name: 'test',
|
|
19
|
+
age: 18,
|
|
20
|
+
}
|
|
21
|
+
const objPut = await oss.putObject('a.json', putJson)
|
|
22
|
+
|
|
23
|
+
console.log(objPut);
|
|
@@ -0,0 +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';
|
|
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}"`;
|
|
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);
|
|
60
|
+
|
|
61
|
+
objectStream.pipe(res, { end: true });
|
|
62
|
+
}
|
|
63
|
+
};
|
|
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
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const standardHeaderKeys = ['content-type', 'cache-control', 'content-disposition', 'content-encoding', 'content-language', 'expires'];
|
|
2
|
+
|
|
3
|
+
export type StandardHeaders = {
|
|
4
|
+
ContentType?: string;
|
|
5
|
+
CacheControl?: string;
|
|
6
|
+
ContentDisposition?: string;
|
|
7
|
+
ContentEncoding?: string;
|
|
8
|
+
ContentLanguage?: string;
|
|
9
|
+
Expires?: Date;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 从元数据中提取标准头部和自定义元数据
|
|
14
|
+
* @param metaData 原始元数据
|
|
15
|
+
* @returns 标准头部和自定义元数据
|
|
16
|
+
*/
|
|
17
|
+
export function extractStandardHeaders(metaData: Record<string, string>): {
|
|
18
|
+
standardHeaders: StandardHeaders;
|
|
19
|
+
customMetadata: Record<string, string>;
|
|
20
|
+
} {
|
|
21
|
+
const standardHeaders: StandardHeaders = {};
|
|
22
|
+
const customMetadata: Record<string, string> = {};
|
|
23
|
+
|
|
24
|
+
for (const [key, value] of Object.entries(metaData)) {
|
|
25
|
+
const lowerKey = key.toLowerCase();
|
|
26
|
+
if (lowerKey === 'content-type') {
|
|
27
|
+
standardHeaders.ContentType = value;
|
|
28
|
+
} else if (lowerKey === 'cache-control') {
|
|
29
|
+
standardHeaders.CacheControl = value;
|
|
30
|
+
} else if (lowerKey === 'content-disposition') {
|
|
31
|
+
standardHeaders.ContentDisposition = value;
|
|
32
|
+
} else if (lowerKey === 'content-encoding') {
|
|
33
|
+
standardHeaders.ContentEncoding = value;
|
|
34
|
+
} else if (lowerKey === 'content-language') {
|
|
35
|
+
standardHeaders.ContentLanguage = value;
|
|
36
|
+
} else if (lowerKey === 'expires') {
|
|
37
|
+
standardHeaders.Expires = new Date(value);
|
|
38
|
+
} else {
|
|
39
|
+
customMetadata[key] = value;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return { standardHeaders, customMetadata };
|
|
44
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
// 获取文件的 content-type
|
|
3
|
+
export const getContentType = (filePath: string) => {
|
|
4
|
+
const extname = path.extname(filePath);
|
|
5
|
+
const contentType = {
|
|
6
|
+
'.html': 'text/html; charset=utf-8',
|
|
7
|
+
'.js': 'text/javascript; charset=utf-8',
|
|
8
|
+
'.css': 'text/css; charset=utf-8',
|
|
9
|
+
'.txt': 'text/plain; charset=utf-8',
|
|
10
|
+
'.json': 'application/json; charset=utf-8',
|
|
11
|
+
'.png': 'image/png',
|
|
12
|
+
'.jpg': 'image/jpg',
|
|
13
|
+
'.gif': 'image/gif',
|
|
14
|
+
'.svg': 'image/svg+xml',
|
|
15
|
+
'.wav': 'audio/wav',
|
|
16
|
+
'.mp4': 'video/mp4',
|
|
17
|
+
'.md': 'text/markdown; charset=utf-8', // utf-8配置
|
|
18
|
+
'.ico': 'image/x-icon', // Favicon 图标
|
|
19
|
+
'.webp': 'image/webp', // WebP 图像格式
|
|
20
|
+
'.webm': 'video/webm', // WebM 视频格式
|
|
21
|
+
'.ogg': 'audio/ogg', // Ogg 音频格式
|
|
22
|
+
'.mp3': 'audio/mpeg', // MP3 音频格式
|
|
23
|
+
'.m4a': 'audio/mp4', // M4A 音频格式
|
|
24
|
+
'.m3u8': 'application/vnd.apple.mpegurl', // HLS 播放列表
|
|
25
|
+
'.ts': 'video/mp2t', // MPEG Transport Stream
|
|
26
|
+
'.pdf': 'application/pdf', // PDF 文档
|
|
27
|
+
'.doc': 'application/msword', // Word 文档
|
|
28
|
+
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // Word 文档 (新版)
|
|
29
|
+
'.ppt': 'application/vnd.ms-powerpoint', // PowerPoint 演示文稿
|
|
30
|
+
'.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // PowerPoint (新版)
|
|
31
|
+
'.xls': 'application/vnd.ms-excel', // Excel 表格
|
|
32
|
+
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // Excel 表格 (新版)
|
|
33
|
+
'.csv': 'text/csv; charset=utf-8', // CSV 文件
|
|
34
|
+
'.xml': 'application/xml; charset=utf-8', // XML 文件
|
|
35
|
+
'.rtf': 'application/rtf', // RTF 文本文件
|
|
36
|
+
'.eot': 'application/vnd.ms-fontobject', // Embedded OpenType 字体
|
|
37
|
+
'.ttf': 'font/ttf', // TrueType 字体
|
|
38
|
+
'.woff': 'font/woff', // Web Open Font Format 1.0
|
|
39
|
+
'.woff2': 'font/woff2', // Web Open Font Format 2.0
|
|
40
|
+
'.otf': 'font/otf', // OpenType 字体
|
|
41
|
+
'.wasm': 'application/wasm', // WebAssembly 文件
|
|
42
|
+
'.pem': 'application/x-pem-file', // PEM 证书文件
|
|
43
|
+
'.crt': 'application/x-x509-ca-cert', // CRT 证书文件
|
|
44
|
+
'.yaml': 'application/x-yaml; charset=utf-8', // YAML 文件
|
|
45
|
+
'.yml': 'application/x-yaml; charset=utf-8', // YAML 文件(别名)
|
|
46
|
+
'.zip': 'application/octet-stream',
|
|
47
|
+
};
|
|
48
|
+
return contentType[extname] || 'application/octet-stream';
|
|
49
|
+
};
|
package/src/util/hash.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
// 582af9ef5cdc53d6628f45cb842f874a
|
|
3
|
+
// const hashStr = '{"a":"a"}';
|
|
4
|
+
// const hash = crypto.createHash('md5').update(hashStr).digest('hex');
|
|
5
|
+
// console.log(hash);
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 计算字符串的md5值
|
|
9
|
+
* @param str
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
export const hash = (str: string | Buffer | Object) => {
|
|
13
|
+
let hashStr: string | Buffer;
|
|
14
|
+
if (str instanceof Buffer) {
|
|
15
|
+
hashStr = str;
|
|
16
|
+
} else if (str instanceof Object) {
|
|
17
|
+
hashStr = JSON.stringify(str, null, 2);
|
|
18
|
+
} else {
|
|
19
|
+
hashStr = str;
|
|
20
|
+
}
|
|
21
|
+
return crypto.createHash('md5').update(hashStr).digest('hex');
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const hashSringify = (str: Object) => {
|
|
25
|
+
return JSON.stringify(str, null, 2);
|
|
26
|
+
};
|
package/dist/index-BGsBfWH-.d.ts
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import * as minio from 'minio';
|
|
2
|
-
import { ItemBucketMetadata, Client } from 'minio';
|
|
3
|
-
import * as minio_dist_esm_internal_type_mjs from 'minio/dist/esm/internal/type.mjs';
|
|
4
|
-
import * as stream from 'stream';
|
|
5
|
-
|
|
6
|
-
type UploadedObjectInfo = {
|
|
7
|
-
etag: string;
|
|
8
|
-
lastModified?: Date;
|
|
9
|
-
size?: number;
|
|
10
|
-
versionId: string;
|
|
11
|
-
metadata?: ItemBucketMetadata;
|
|
12
|
-
};
|
|
13
|
-
type StatObjectResult = {
|
|
14
|
-
size: number;
|
|
15
|
-
etag: string;
|
|
16
|
-
lastModified: Date;
|
|
17
|
-
metaData: ItemBucketMetadata;
|
|
18
|
-
versionId?: string | null;
|
|
19
|
-
};
|
|
20
|
-
type ListFileObject = {
|
|
21
|
-
name: string;
|
|
22
|
-
size: number;
|
|
23
|
-
lastModified: Date;
|
|
24
|
-
etag: string;
|
|
25
|
-
};
|
|
26
|
-
type ListDirectoryObject = {
|
|
27
|
-
prefix: string;
|
|
28
|
-
size: number;
|
|
29
|
-
};
|
|
30
|
-
type ListObjectResult = ListFileObject | ListDirectoryObject;
|
|
31
|
-
interface OssBaseOperation {
|
|
32
|
-
prefix: string;
|
|
33
|
-
setPrefix(prefix: string): void;
|
|
34
|
-
/**
|
|
35
|
-
* 获取对象
|
|
36
|
-
* @param objectName 对象名
|
|
37
|
-
*/
|
|
38
|
-
getObject(objectName: string): Promise<any>;
|
|
39
|
-
/**
|
|
40
|
-
* 上传对象
|
|
41
|
-
* @param objectName 对象名
|
|
42
|
-
* @param data 数据
|
|
43
|
-
*/
|
|
44
|
-
putObject(objectName: string, data: Buffer | string, metaData?: ItemBucketMetadata): Promise<UploadedObjectInfo>;
|
|
45
|
-
/**
|
|
46
|
-
* 上传文件
|
|
47
|
-
* @param objectName 对象名
|
|
48
|
-
* @param filePath 文件路径
|
|
49
|
-
*/
|
|
50
|
-
fPutObject(objectName: string, filePath: string, metaData?: ItemBucketMetadata): Promise<UploadedObjectInfo>;
|
|
51
|
-
/**
|
|
52
|
-
* 获取对象信息
|
|
53
|
-
* @param objectName 对象名
|
|
54
|
-
*/
|
|
55
|
-
statObject(objectName: string): Promise<StatObjectResult>;
|
|
56
|
-
/**
|
|
57
|
-
* 删除对象
|
|
58
|
-
* @param objectName 对象名
|
|
59
|
-
*/
|
|
60
|
-
deleteObject(objectName: string): Promise<any>;
|
|
61
|
-
/**
|
|
62
|
-
* 列出对象
|
|
63
|
-
* @param objectName 对象名
|
|
64
|
-
* @param opts 选项
|
|
65
|
-
* @param opts.recursive 是否递归
|
|
66
|
-
* @param opts.startAfter 开始位置
|
|
67
|
-
*/
|
|
68
|
-
listObjects(objectName: string, opts?: {
|
|
69
|
-
/**
|
|
70
|
-
* 是否递归
|
|
71
|
-
*/
|
|
72
|
-
recursive?: boolean;
|
|
73
|
-
/**
|
|
74
|
-
* 开始位置
|
|
75
|
-
*/
|
|
76
|
-
startAfter?: string;
|
|
77
|
-
}): Promise<ListObjectResult[]>;
|
|
78
|
-
/**
|
|
79
|
-
* 复制对象
|
|
80
|
-
* @param sourceObject 源对象
|
|
81
|
-
* @param targetObject 目标对象
|
|
82
|
-
*/
|
|
83
|
-
copyObject: Client['copyObject'];
|
|
84
|
-
}
|
|
85
|
-
interface OssService extends OssBaseOperation {
|
|
86
|
-
owner: string;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
type OssBaseOptions<T = {
|
|
90
|
-
[key: string]: any;
|
|
91
|
-
}> = {
|
|
92
|
-
/**
|
|
93
|
-
* 已经初始化好的minio client
|
|
94
|
-
*/
|
|
95
|
-
client: Client;
|
|
96
|
-
/**
|
|
97
|
-
* 桶名
|
|
98
|
-
*/
|
|
99
|
-
bucketName: string;
|
|
100
|
-
/**
|
|
101
|
-
* 前缀
|
|
102
|
-
*/
|
|
103
|
-
prefix?: string;
|
|
104
|
-
} & T;
|
|
105
|
-
declare class OssBase implements OssBaseOperation {
|
|
106
|
-
client?: Client;
|
|
107
|
-
bucketName: string;
|
|
108
|
-
prefix: string;
|
|
109
|
-
/**
|
|
110
|
-
* 计算字符串或者对象的的md5值
|
|
111
|
-
*/
|
|
112
|
-
hash: (str: string | Buffer | Object) => string;
|
|
113
|
-
constructor(opts: OssBaseOptions);
|
|
114
|
-
setPrefix(prefix: string): void;
|
|
115
|
-
getObject(objectName: string): Promise<stream.Readable>;
|
|
116
|
-
getJson(objectName: string): Promise<Record<string, any>>;
|
|
117
|
-
/**
|
|
118
|
-
* 上传文件, 当是流的时候,中断之后的etag会变,所以传递的时候不要嵌套async await,例如 busboy 监听文件流内部的时候,不要用check
|
|
119
|
-
* @param objectName
|
|
120
|
-
* @param data
|
|
121
|
-
* @param metaData
|
|
122
|
-
* @param options 如果文件本身存在,则复制原有的meta的内容
|
|
123
|
-
* @returns
|
|
124
|
-
*/
|
|
125
|
-
putObject(objectName: string, data: Buffer | string | Object, metaData?: ItemBucketMetadata, opts?: {
|
|
126
|
-
check?: boolean;
|
|
127
|
-
isStream?: boolean;
|
|
128
|
-
size?: number;
|
|
129
|
-
}): Promise<minio_dist_esm_internal_type_mjs.UploadedObjectInfo>;
|
|
130
|
-
deleteObject(objectName: string): Promise<void>;
|
|
131
|
-
listObjects<IS_FILE = false>(objectName: string, opts?: {
|
|
132
|
-
recursive?: boolean;
|
|
133
|
-
startAfter?: string;
|
|
134
|
-
}): Promise<IS_FILE extends true ? ListFileObject[] : ListObjectResult[]>;
|
|
135
|
-
fPutObject(objectName: string, filePath: string, metaData?: ItemBucketMetadata): Promise<any>;
|
|
136
|
-
statObject(objectName: string, checkFile?: boolean): Promise<minio.BucketItemStat>;
|
|
137
|
-
/**
|
|
138
|
-
* 检查文件hash是否一致
|
|
139
|
-
* @param objectName
|
|
140
|
-
* @param hash
|
|
141
|
-
* @returns
|
|
142
|
-
*/
|
|
143
|
-
checkObjectHash(objectName: string, hash: string, meta?: ItemBucketMetadata): Promise<{
|
|
144
|
-
success: boolean;
|
|
145
|
-
metaData: ItemBucketMetadata | null;
|
|
146
|
-
obj: any;
|
|
147
|
-
equalMeta?: boolean;
|
|
148
|
-
}>;
|
|
149
|
-
getMetadata(pathname: string, meta?: ItemBucketMetadata): ItemBucketMetadata;
|
|
150
|
-
copyObject(sourceObject: any, targetObject: any): Promise<minio_dist_esm_internal_type_mjs.CopyObjectResult>;
|
|
151
|
-
replaceObject(objectName: string, meta: {
|
|
152
|
-
[key: string]: string;
|
|
153
|
-
}): Promise<minio_dist_esm_internal_type_mjs.CopyObjectResult>;
|
|
154
|
-
static create<T extends OssBase, U>(this: new (opts: OssBaseOptions<U>) => T, opts: OssBaseOptions<U>): T;
|
|
155
|
-
static fromBase<T extends OssBase, U>(this: new (opts: OssBaseOptions<U>) => T, createOpts: {
|
|
156
|
-
oss: OssBase;
|
|
157
|
-
opts: Partial<OssBaseOptions<U>>;
|
|
158
|
-
}): T;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export { type ListFileObject as L, OssBase as O, type StatObjectResult as S, type UploadedObjectInfo as U, type OssBaseOptions as a, type ListDirectoryObject as b, type ListObjectResult as c, type OssBaseOperation as d, type OssService as e };
|