Files
code-center/src/routes/file/module/get-minio-list.ts

180 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import dayjs from 'dayjs';
import { oss } from '@/modules/s3.ts';
import { StatObjectResult } from '@kevisual/oss';
import { UserId } from '@/routes/user/modules/user-id.ts';
type MinioListOpt = {
prefix: string;
recursive?: boolean;
};
export type MinioFile = {
name: string;
size: number;
lastModified: Date;
etag: string;
};
export type MinioDirectory = {
prefix: string;
size: number;
};
export type MinioList = (MinioFile | MinioDirectory)[];
export const getMinioList = async <IS_FILE extends boolean>(opts: MinioListOpt): Promise<IS_FILE extends true ? MinioFile[] : MinioDirectory[]> => {
const prefix = opts.prefix;
const recursive = opts.recursive ?? false;
const res = await oss.listObjects(prefix, { recursive });
return res as IS_FILE extends true ? MinioFile[] : MinioDirectory[];
};
export const getFileStat = async (prefix: string, isFile?: boolean): Promise<StatObjectResult | null> => {
try {
const obj = await oss.statObject(prefix);
if (isFile && obj?.size === 0) {
return null;
}
return obj;
} catch (e) {
if (e.code === 'NotFound') {
return null;
}
console.error('get File Stat Error not handle', e);
return null;
}
};
export const deleteFile = async (prefix: string): Promise<{ code: number; message: string }> => {
try {
const fileStat = await getFileStat(prefix);
if (!fileStat) {
console.warn(`File not found: ${prefix}`);
return {
code: 404,
message: 'file not found',
};
}
await oss.deleteObject(prefix);
return {
code: 200,
message: 'delete success',
};
} catch (e) {
console.error('delete File Error not handle', e);
return {
code: 500,
message: 'delete failed',
};
}
};
export const deleteFileByPrefix = async (prefix: string): Promise<any> => {
try {
const objects = await oss.listObjects<true>(prefix, { recursive: true });
if (objects.length > 0) {
for (const obj of objects) {
await oss.deleteObject(obj.name);
}
}
return true;
} catch (e) {
console.error('delete File Error not handle', e);
return false;
}
};
type GetMinioListAndSetToAppListOpts = {
username: string;
appKey: string;
version: string;
};
// 批量列出文件并设置到appList的files中
export const getMinioListAndSetToAppList = async (opts: GetMinioListAndSetToAppListOpts) => {
const { username, appKey, version } = opts;
const uid = await UserId.getUserIdByName(username);
const minioList = await getMinioList({ prefix: `data/${uid}/${appKey}/${version}`, recursive: true });
const files = minioList;
return files as MinioFile[];
};
/**
* 更新文件的元数据
* @param prefix 文件前缀
* @param newMetadata 新的元数据
* @returns
*/
export const updateFileStat = async (
prefix: string,
newMetadata: Record<string, string>,
): Promise<{
code: number;
data: any;
message?: string;
}> => {
try {
const copyResult = await oss.replaceObject(prefix, {
...newMetadata
});
console.log('copyResult', copyResult);
console.log(`Metadata for ${prefix} updated successfully.`);
return {
code: 200,
data: copyResult,
message: 'update metadata success',
};
} catch (e) {
console.error('Error updating file stat', e);
return {
code: 500,
data: null,
message: `update metadata failed. ${e.message}`,
};
}
};
/**
* 将用户A的文件移动到用户B
* @param usernameA
* @param usernameB
* @param clearOldUser 是否清除用户A的文件
*/
export const mvUserAToUserB = async (usernameA: string, usernameB: string, clearOldUser = false) => {
const oldPrefix = `${usernameA}/`;
const newPrefix = `${usernameB}/`;
const listSource = await getMinioList<true>({ prefix: oldPrefix, recursive: true });
for (const item of listSource) {
const newName = item.name.slice(oldPrefix.length);
await oss.copyObject(item.name, `${newPrefix}${newName}`);
}
if (clearOldUser) {
const files = await getMinioList<true>({ prefix: oldPrefix, recursive: true });
for (const file of files) {
await oss.deleteObject(file.name);
}
}
console.log(`移动 ${usernameA} to ${usernameB} success`);
};
export const backupUserA = async (usernameA: string, id: string, backName?: string) => {
const today = backName || dayjs().format('YYYY-MM-DD-HH-mm');
const backupAllPrefix = `private/backup/${id}/`;
const backupPrefix = `private/backup/${id}/${today}`;
const backupList = await getMinioList<false>({ prefix: backupAllPrefix });
const backupListSort = backupList.sort((a, b) => -a.prefix.localeCompare(b.prefix));
if (backupListSort.length > 2) {
const deleteBackup = backupListSort.slice(2);
for (const item of deleteBackup) {
const files = await getMinioList<true>({ prefix: item.prefix, recursive: true });
for (const file of files) {
await oss.deleteObject(file.name);
}
}
}
await mvUserAToUserB(usernameA, backupPrefix, false);
console.log(`Backup user ${usernameA} to ${backupPrefix} success`);
};
/**
* 删除用户
* @param username
*/
export const deleteUser = async (username: string) => {
const uid = await UserId.getUserIdByName(username);
const list = await getMinioList<true>({ prefix: `data/${uid}/`, recursive: true });
for (const item of list) {
await oss.deleteObject(item.name);
}
};