oa_based/src/modules/netdisk/manager/manage.service.ts

795 lines
26 KiB
TypeScript
Raw Normal View History

2024-02-28 17:02:46 +08:00
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { isEmpty } from 'lodash';
import { ConfigKeyPaths } from '~/config';
2024-03-21 15:03:07 +08:00
import { generateRandomValue } from '~/utils';
2024-02-28 17:02:46 +08:00
import { SFileInfo, SFileInfoDetail, SFileList } from './manage.class';
2024-03-21 15:03:07 +08:00
import { InjectMinio } from 'nestjs-minio';
import { Client } from 'minio';
2024-02-28 08:32:35 +08:00
@Injectable()
export class NetDiskManageService {
2024-03-08 16:24:29 +08:00
private get ossConfig() {
2024-02-28 17:02:46 +08:00
return this.configService.get('oss', { infer: true });
2024-02-28 08:32:35 +08:00
}
2024-03-21 15:03:07 +08:00
constructor(
private configService: ConfigService<ConfigKeyPaths>,
@InjectMinio() private readonly minioClient: Client
) {}
2024-02-28 08:32:35 +08:00
/**
*
* @param prefix
* @param marker
* @returns iFileListResult
*/
async getFileList(prefix = '', marker = '', skey = ''): Promise<SFileList> {
// 是否需要搜索
2024-02-28 17:02:46 +08:00
const searching = !isEmpty(skey);
2024-02-28 08:32:35 +08:00
return new Promise<SFileList>((resolve, reject) => {
2024-03-08 16:24:29 +08:00
try {
const fileStream = this.minioClient.listObjects(this.ossConfig.bucket, prefix, false);
2024-03-27 14:18:11 +08:00
this.readStreamData<any>(fileStream).then(respBody => {
2024-03-08 16:24:29 +08:00
console.log(respBody);
const dirs = respBody.filter(item => 'prefix' in item).map(item => item.prefix);
const files = respBody.filter(item => !('prefix' in item));
// 如果这个nextMarker不为空那么还有未列举完毕的文件列表下次调用listPrefix的时候
// 指定options里面的marker为这个值
const fileList: SFileInfo[] = [];
// 处理目录,但只有非搜索模式下可用
if (!searching && !isEmpty(dirs)) {
// dir
for (const dirPath of dirs) {
const name = (dirPath as string).substr(0, dirPath.length - 1).replace(prefix, '');
if (isEmpty(skey) || name.includes(skey)) {
fileList.push({
name: (dirPath as string).substr(0, dirPath.length - 1).replace(prefix, ''),
type: 'dir',
id: generateRandomValue(10)
});
2024-02-28 08:32:35 +08:00
}
}
2024-03-08 16:24:29 +08:00
}
// handle items
if (!isEmpty(files)) {
// file
for (const item of files) {
// 搜索模式下处理
// if (searching) {
// const pathList: string[] = item.key.split(NETDISK_DELIMITER);
// // dir is empty stirng, file is key string
// const name = pathList.pop();
// if (
// item.key.endsWith(NETDISK_DELIMITER) &&
// pathList[pathList.length - 1].includes(skey)
// ) {
// // 结果是目录
// const ditName = pathList.pop();
// fileList.push({
// id: generateRandomValue(10),
// name: ditName,
// type: 'dir',
// belongTo: pathList.join(NETDISK_DELIMITER)
// });
// } else if (name.includes(skey)) {
// // 文件
// fileList.push({
// id: generateRandomValue(10),
// name,
// type: 'file',
// fsize: item.fsize,
// mimeType: item.mimeType,
// putTime: new Date(Number.parseInt(item.putTime) / 10000),
// belongTo: pathList.join(NETDISK_DELIMITER)
// });
// }
// } else {
// 正常获取列表
const fileKey = item.name.replace(prefix, '') as string;
if (!isEmpty(fileKey)) {
fileList.push({
id: generateRandomValue(10),
name: fileKey,
type: 'file',
fsize: `${item.size || 0}`,
mimeType: item.name.split('.').pop(),
putTime: new Date(item.lastModified)
});
// }
2024-02-28 08:32:35 +08:00
}
}
}
2024-03-08 16:24:29 +08:00
resolve({
list: fileList
// marker: respBody.marker || null
});
});
} catch (e) {
reject(e);
}
2024-02-28 17:02:46 +08:00
});
2024-02-28 08:32:35 +08:00
}
/**
*
*/
async getFileInfo(name: string, path: string): Promise<SFileInfoDetail> {
2024-03-08 16:24:29 +08:00
const respBody = await this.minioClient.statObject(this.ossConfig.bucket, `${path}${name}`);
const detailInfo: SFileInfoDetail = {
fsize: respBody.size,
hash: respBody.metaData.hash || '',
md5: respBody.metaData.md5 || '',
mimeType: respBody.metaData['content-type'],
putTime: new Date(respBody.lastModified)
};
return detailInfo;
2024-02-28 08:32:35 +08:00
}
2024-03-08 16:24:29 +08:00
// /**
// * 修改文件MimeType
// */
// async changeFileHeaders(
// name: string,
// path: string,
// headers: { [k: string]: string }
// ): Promise<void> {
// return new Promise((resolve, reject) => {
// this.bucketManager.changeHeaders(
// this.qiniuConfig.bucket,
// `${path}${name}`,
// headers,
// (err, _, respInfo) => {
// if (err) {
// reject(err);
// return;
// }
// if (respInfo.statusCode === 200) {
// resolve();
// } else {
// reject(
// new Error(`Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`)
// );
// }
// }
// );
// });
// }
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// /**
// * 创建文件夹
// * @returns true创建成功
// */
// async createDir(dirName: string): Promise<void> {
// const safeDirName = dirName.endsWith('/') ? dirName : `${dirName}/`;
// return new Promise((resolve, reject) => {
// // 上传一个空文件以用于显示文件夹效果
// const formUploader = new qiniu.form_up.FormUploader(this.config);
// const putExtra = new qiniu.form_up.PutExtra();
// formUploader.put(
// this.createUploadToken(''),
// safeDirName,
// ' ',
// putExtra,
// (respErr, respBody, respInfo) => {
// if (respErr) {
// reject(respErr);
// return;
// }
// if (respInfo.statusCode === 200) {
// resolve();
// } else {
// reject(
// new Error(`Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`)
// );
// }
// }
// );
// });
// }
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// /**
// * 检查文件是否存在,同可检查目录
// */
// async checkFileExist(filePath: string): Promise<boolean> {
// return new Promise((resolve, reject) => {
// // fix path end must a /
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// // 检测文件夹是否存在
// this.bucketManager.stat(this.qiniuConfig.bucket, filePath, (respErr, respBody, respInfo) => {
// if (respErr) {
// reject(respErr);
// return;
// }
// if (respInfo.statusCode === 200) {
// // 文件夹存在
// resolve(true);
// } else if (respInfo.statusCode === 612) {
// // 文件夹不存在
// resolve(false);
// } else {
// reject(
// new Error(`Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`)
// );
// }
// });
// });
// }
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// /**
// * 创建Upload Token, 默认过期时间一小时
// * @returns upload token
// */
// createUploadToken(endUser: string): string {
// const policy = new qiniu.rs.PutPolicy({
// scope: this.qiniuConfig.bucket,
// insertOnly: 1,
// fsizeLimit: 1024 ** 2 * 10,
// endUser
// });
// const uploadToken = policy.uploadToken(this.mac);
// return uploadToken;
// }
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// /**
// * 重命名文件
// * @param dir 文件路径
// * @param name 文件名称
// */
// async renameFile(dir: string, name: string, toName: string): Promise<void> {
// const fileName = `${dir}${name}`;
// const toFileName = `${dir}${toName}`;
// const op = {
// force: true
// };
// return new Promise((resolve, reject) => {
// this.bucketManager.move(
// this.qiniuConfig.bucket,
// fileName,
// this.qiniuConfig.bucket,
// toFileName,
// op,
// (err, respBody, respInfo) => {
// if (err) {
// reject(err);
// } else {
// if (respInfo.statusCode === 200) {
// resolve();
// } else {
// reject(
// new Error(
// `Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`
// )
// );
// }
// }
// }
// );
// });
// }
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// /**
// * 移动文件
// */
// async moveFile(dir: string, toDir: string, name: string): Promise<void> {
// const fileName = `${dir}${name}`;
// const toFileName = `${toDir}${name}`;
// const op = {
// force: true
// };
// return new Promise((resolve, reject) => {
// this.bucketManager.move(
// this.qiniuConfig.bucket,
// fileName,
// this.qiniuConfig.bucket,
// toFileName,
// op,
// (err, respBody, respInfo) => {
// if (err) {
// reject(err);
// } else {
// if (respInfo.statusCode === 200) {
// resolve();
// } else {
// reject(
// new Error(
// `Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`
// )
// );
// }
// }
// }
// );
// });
// }
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// /**
// * 复制文件
// */
// async copyFile(dir: string, toDir: string, name: string): Promise<void> {
// const fileName = `${dir}${name}`;
// // 拼接文件名
// const ext = extname(name);
// const bn = basename(name, ext);
// const toFileName = `${toDir}${bn}${NETDISK_COPY_SUFFIX}${ext}`;
// const op = {
// force: true
// };
// return new Promise((resolve, reject) => {
// this.bucketManager.copy(
// this.qiniuConfig.bucket,
// fileName,
// this.qiniuConfig.bucket,
// toFileName,
// op,
// (err, respBody, respInfo) => {
// if (err) {
// reject(err);
// } else {
// if (respInfo.statusCode === 200) {
// resolve();
// } else {
// reject(
// new Error(
// `Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`
// )
// );
// }
// }
// }
// );
// });
// }
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// /**
// * 重命名文件夹
// */
// async renameDir(path: string, name: string, toName: string): Promise<void> {
// const dirName = `${path}${name}`;
// const toDirName = `${path}${toName}`;
// let hasFile = true;
// let marker = '';
// const op = {
// force: true
// };
// const bucketName = this.qiniuConfig.bucket;
// while (hasFile) {
// await new Promise<void>((resolve, reject) => {
// // 列举当前目录下的所有文件
// this.bucketManager.listPrefix(
// this.qiniuConfig.bucket,
// {
// prefix: dirName,
// limit: NETDISK_HANDLE_MAX_ITEM,
// marker
// },
// (err, respBody, respInfo) => {
// if (err) {
// reject(err);
// return;
// }
// if (respInfo.statusCode === 200) {
// const moveOperations = respBody.items.map(item => {
// const { key } = item;
// const destKey = key.replace(dirName, toDirName);
// return qiniu.rs.moveOp(bucketName, key, bucketName, destKey, op);
// });
// this.bucketManager.batch(moveOperations, (err2, respBody2, respInfo2) => {
// if (err2) {
// reject(err2);
// return;
// }
// if (respInfo2.statusCode === 200) {
// if (isEmpty(respBody.marker)) hasFile = false;
// else marker = respBody.marker;
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// resolve();
// } else {
// reject(
// new Error(
// `Qiniu Error Code: ${respInfo2.statusCode}, Info: ${respInfo2.statusMessage}`
// )
// );
// }
// });
// } else {
// reject(
// new Error(
// `Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`
// )
// );
// }
// }
// );
// });
// }
// }
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// /**
// * 获取七牛下载的文件url链接
// * @param key 文件路径
// * @returns 连接
// */
getDownloadLink(key: string): Promise<string> {
2024-02-28 08:32:35 +08:00
return new Promise((resolve, reject) => {
2024-03-08 16:24:29 +08:00
if (this.ossConfig.access === 'public') {
this.minioClient.presignedUrl(
'GET',
this.ossConfig.bucket,
key,
24 * 60 * 60,
(err, presignedUrl) => {
if (err) reject();
resolve(presignedUrl);
2024-02-28 08:32:35 +08:00
}
2024-03-08 16:24:29 +08:00
);
} else if (this.ossConfig.access === 'private') {
// return this.bucketManager.privateDownloadUrl(
// this.qiniuConfig.domain,
// key,
// Date.now() / 1000 + 36000
// );
}
2024-02-28 17:02:46 +08:00
});
2024-02-28 08:32:35 +08:00
}
2024-03-08 16:24:29 +08:00
// /**
// * 删除文件
// * @param dir 删除的文件夹目录
// * @param name 文件名
// */
// async deleteFile(dir: string, name: string): Promise<void> {
// return new Promise((resolve, reject) => {
// this.bucketManager.delete(
// this.qiniuConfig.bucket,
// `${dir}${name}`,
// (err, respBody, respInfo) => {
// if (err) {
// reject(err);
// return;
// }
// if (respInfo.statusCode === 200) {
// resolve();
// } else {
// reject(
// new Error(`Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`)
// );
// }
// }
// );
// });
// }
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// /**
// * 删除文件夹
// * @param dir 文件夹所在的上级目录
// * @param name 文件目录名称
// */
// async deleteMultiFileOrDir(fileList: FileOpItem[], dir: string): Promise<void> {
// const files = fileList.filter(item => item.type === 'file');
// if (files.length > 0) {
// // 批处理文件
// const copyOperations = files.map(item => {
// const fileName = `${dir}${item.name}`;
// return qiniu.rs.deleteOp(this.qiniuConfig.bucket, fileName);
// });
// await new Promise<void>((resolve, reject) => {
// this.bucketManager.batch(copyOperations, (err, respBody, respInfo) => {
// if (err) {
// reject(err);
// return;
// }
// if (respInfo.statusCode === 200) {
// resolve();
// } else if (respInfo.statusCode === 298) {
// reject(new Error('操作异常,但部分文件夹删除成功'));
// } else {
// reject(
// new Error(`Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`)
// );
// }
// });
// });
// }
// // 处理文件夹
// const dirs = fileList.filter(item => item.type === 'dir');
// if (dirs.length > 0) {
// // 处理文件夹的复制
// for (let i = 0; i < dirs.length; i++) {
// const dirName = `${dir}${dirs[i].name}/`;
// let hasFile = true;
// let marker = '';
// while (hasFile) {
// await new Promise<void>((resolve, reject) => {
// // 列举当前目录下的所有文件
// this.bucketManager.listPrefix(
// this.qiniuConfig.bucket,
// {
// prefix: dirName,
// limit: NETDISK_HANDLE_MAX_ITEM,
// marker
// },
// (err, respBody, respInfo) => {
// if (err) {
// reject(err);
// return;
// }
// if (respInfo.statusCode === 200) {
// const moveOperations = respBody.items.map(item => {
// const { key } = item;
// return qiniu.rs.deleteOp(this.qiniuConfig.bucket, key);
// });
// this.bucketManager.batch(moveOperations, (err2, respBody2, respInfo2) => {
// if (err2) {
// reject(err2);
// return;
// }
// if (respInfo2.statusCode === 200) {
// if (isEmpty(respBody.marker)) hasFile = false;
// else marker = respBody.marker;
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// resolve();
// } else {
// reject(
// new Error(
// `Qiniu Error Code: ${respInfo2.statusCode}, Info: ${respInfo2.statusMessage}`
// )
// );
// }
// });
// } else {
// reject(
// new Error(
// `Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`
// )
// );
// }
// }
// );
// });
// }
// }
// }
// }
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// /**
// * 复制文件,含文件夹
// */
// async copyMultiFileOrDir(fileList: FileOpItem[], dir: string, toDir: string): Promise<void> {
// const files = fileList.filter(item => item.type === 'file');
// const op = {
// force: true
// };
// if (files.length > 0) {
// // 批处理文件
// const copyOperations = files.map(item => {
// const fileName = `${dir}${item.name}`;
// // 拼接文件名
// const ext = extname(item.name);
// const bn = basename(item.name, ext);
// const toFileName = `${toDir}${bn}${NETDISK_COPY_SUFFIX}${ext}`;
// return qiniu.rs.copyOp(
// this.qiniuConfig.bucket,
// fileName,
// this.qiniuConfig.bucket,
// toFileName,
// op
// );
// });
// await new Promise<void>((resolve, reject) => {
// this.bucketManager.batch(copyOperations, (err, respBody, respInfo) => {
// if (err) {
// reject(err);
// return;
// }
// if (respInfo.statusCode === 200) {
// resolve();
// } else if (respInfo.statusCode === 298) {
// reject(new Error('操作异常,但部分文件夹删除成功'));
// } else {
// reject(
// new Error(`Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`)
// );
// }
// });
// });
// }
// // 处理文件夹
// const dirs = fileList.filter(item => item.type === 'dir');
// if (dirs.length > 0) {
// // 处理文件夹的复制
// for (let i = 0; i < dirs.length; i++) {
// const dirName = `${dir}${dirs[i].name}/`;
// const copyDirName = `${toDir}${dirs[i].name}${NETDISK_COPY_SUFFIX}/`;
// let hasFile = true;
// let marker = '';
// while (hasFile) {
// await new Promise<void>((resolve, reject) => {
// // 列举当前目录下的所有文件
// this.bucketManager.listPrefix(
// this.qiniuConfig.bucket,
// {
// prefix: dirName,
// limit: NETDISK_HANDLE_MAX_ITEM,
// marker
// },
// (err, respBody, respInfo) => {
// if (err) {
// reject(err);
// return;
// }
// if (respInfo.statusCode === 200) {
// const moveOperations = respBody.items.map(item => {
// const { key } = item;
// const destKey = key.replace(dirName, copyDirName);
// return qiniu.rs.copyOp(
// this.qiniuConfig.bucket,
// key,
// this.qiniuConfig.bucket,
// destKey,
// op
// );
// });
// this.bucketManager.batch(moveOperations, (err2, respBody2, respInfo2) => {
// if (err2) {
// reject(err2);
// return;
// }
// if (respInfo2.statusCode === 200) {
// if (isEmpty(respBody.marker)) hasFile = false;
// else marker = respBody.marker;
2024-02-28 08:32:35 +08:00
2024-03-08 16:24:29 +08:00
// resolve();
// } else {
// reject(
// new Error(
// `Qiniu Error Code: ${respInfo2.statusCode}, Info: ${respInfo2.statusMessage}`
// )
// );
// }
// });
// } else {
// reject(
// new Error(
// `Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`
// )
// );
// }
// }
// );
// });
// }
// }
// }
// }
// /**
// * 移动文件,含文件夹
// */
// async moveMultiFileOrDir(fileList: FileOpItem[], dir: string, toDir: string): Promise<void> {
// const files = fileList.filter(item => item.type === 'file');
// const op = {
// force: true
// };
// if (files.length > 0) {
// // 批处理文件
// const copyOperations = files.map(item => {
// const fileName = `${dir}${item.name}`;
// const toFileName = `${toDir}${item.name}`;
// return qiniu.rs.moveOp(
// this.qiniuConfig.bucket,
// fileName,
// this.qiniuConfig.bucket,
// toFileName,
// op
// );
// });
// await new Promise<void>((resolve, reject) => {
// this.bucketManager.batch(copyOperations, (err, respBody, respInfo) => {
// if (err) {
// reject(err);
// return;
// }
// if (respInfo.statusCode === 200) {
// resolve();
// } else if (respInfo.statusCode === 298) {
// reject(new Error('操作异常,但部分文件夹删除成功'));
// } else {
// reject(
// new Error(`Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`)
// );
// }
// });
// });
// }
// // 处理文件夹
// const dirs = fileList.filter(item => item.type === 'dir');
// if (dirs.length > 0) {
// // 处理文件夹的复制
// for (let i = 0; i < dirs.length; i++) {
// const dirName = `${dir}${dirs[i].name}/`;
// const toDirName = `${toDir}${dirs[i].name}/`;
// // 移动的目录不是是自己
// if (toDirName.startsWith(dirName)) continue;
// let hasFile = true;
// let marker = '';
// while (hasFile) {
// await new Promise<void>((resolve, reject) => {
// // 列举当前目录下的所有文件
// this.bucketManager.listPrefix(
// this.qiniuConfig.bucket,
// {
// prefix: dirName,
// limit: NETDISK_HANDLE_MAX_ITEM,
// marker
// },
// (err, respBody, respInfo) => {
// if (err) {
// reject(err);
// return;
// }
// if (respInfo.statusCode === 200) {
// const moveOperations = respBody.items.map(item => {
// const { key } = item;
// const destKey = key.replace(dirName, toDirName);
// return qiniu.rs.moveOp(
// this.qiniuConfig.bucket,
// key,
// this.qiniuConfig.bucket,
// destKey,
// op
// );
// });
// this.bucketManager.batch(moveOperations, (err2, respBody2, respInfo2) => {
// if (err2) {
// reject(err2);
// return;
// }
// if (respInfo2.statusCode === 200) {
// if (isEmpty(respBody.marker)) hasFile = false;
// else marker = respBody.marker;
// resolve();
// } else {
// reject(
// new Error(
// `Qiniu Error Code: ${respInfo2.statusCode}, Info: ${respInfo2.statusMessage}`
// )
// );
// }
// });
// } else {
// reject(
// new Error(
// `Qiniu Error Code: ${respInfo.statusCode}, Info: ${respInfo.statusMessage}`
// )
// );
// }
// }
// );
// });
// }
// }
// }
// }
2024-02-28 08:32:35 +08:00
/**
2024-03-08 16:24:29 +08:00
*
* @param stream
* @returns []
2024-02-28 08:32:35 +08:00
*/
2024-03-08 16:24:29 +08:00
readStreamData<T>(stream): Promise<T[]> {
return new Promise((resolve, reject) => {
const result: T[] = [];
stream
.on('data', function (row) {
result.push(row);
})
.on('end', function () {
resolve(result);
})
.on('error', function (error) {
reject(error);
2024-02-28 17:02:46 +08:00
});
2024-03-08 16:24:29 +08:00
});
2024-02-28 08:32:35 +08:00
}
}