172 lines
4.9 KiB
JavaScript
172 lines
4.9 KiB
JavaScript
import COS from 'cos-nodejs-sdk-v5';
|
|
import OSS from 'ali-oss';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
class StorageManager {
|
|
constructor(config) {
|
|
this.config = config;
|
|
this.storageType = (config.STORAGE_TYPE || 'local').toLowerCase();
|
|
|
|
// 初始化COS客户端
|
|
if (this.storageType === 'cos' && config.COS_SECRET_ID && config.COS_SECRET_KEY) {
|
|
const cosConfig = {
|
|
SecretId: config.COS_SECRET_ID,
|
|
SecretKey: config.COS_SECRET_KEY,
|
|
};
|
|
this.cosClient = new COS(cosConfig);
|
|
}
|
|
|
|
// 初始化OSS客户端
|
|
if (this.storageType === 'oss') {
|
|
const ossConfig = {
|
|
region: config.OSS_REGION,
|
|
accessKeyId: config.OSS_ACCESS_KEY_ID,
|
|
accessKeySecret: config.OSS_ACCESS_KEY_SECRET,
|
|
bucket: config.OSS_BUCKET
|
|
};
|
|
|
|
if (ossConfig.accessKeyId && ossConfig.accessKeySecret && ossConfig.region && ossConfig.bucket) {
|
|
this.ossClient = new OSS(ossConfig);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 上传文件
|
|
* @param basePath 应用根路径
|
|
* @param upload_path 上传路径
|
|
* @param filename 文件名
|
|
* @returns {Promise<*>}
|
|
*/
|
|
async upload(basePath, upload_path, filename) {
|
|
switch (this.storageType.toLowerCase()) {
|
|
case 'oss':
|
|
return this.uploadToOSS(basePath, upload_path, filename);
|
|
|
|
case 'cos':
|
|
return this.uploadToCOS(basePath, upload_path, filename);
|
|
|
|
case 'local':
|
|
return this.uploadToLocal(basePath, upload_path, filename);
|
|
|
|
default:
|
|
return this.uploadToCOS(basePath, upload_path, filename);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 上传文件到本地
|
|
* @param basePath 应用根路径
|
|
* @param upload_path 上传路径
|
|
* @param filename 文件名
|
|
* @returns {Promise<*>}
|
|
*/
|
|
async uploadToLocal(basePath, upload_path, filename) {
|
|
const date = new Date();
|
|
const pathDir = `${upload_path}/${date.getFullYear()}${date.getMonth() + 1}/${date.getDate()}`;
|
|
const localFilePath = `${basePath}/${upload_path}/${filename}`;
|
|
const targetDir = `${basePath}/${pathDir}`;
|
|
|
|
// 确保目标目录存在
|
|
await fs.promises.mkdir(targetDir, { recursive: true });
|
|
|
|
// 移动文件到目标位置
|
|
const targetPath = `${targetDir}/${filename}`;
|
|
await fs.promises.rename(localFilePath, targetPath);
|
|
|
|
// 构造访问URL
|
|
const localDomain = process.env.LOCAL_DOMAIN || 'http://localhost:3000';
|
|
const url = `${localDomain}/${pathDir}/${filename}`;
|
|
|
|
return {
|
|
name: filename,
|
|
path: url
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 上传文件到COS
|
|
* @param basePath 应用根路径
|
|
* @param upload_path 上传路径
|
|
* @param filename 文件名
|
|
* @returns {Promise<*>}
|
|
*/
|
|
async uploadToCOS(basePath, upload_path, filename) {
|
|
const date = new Date();
|
|
const path = `${upload_path}/${date.getFullYear()}${date.getMonth() + 1}/${date.getDate()}`;
|
|
const localFilePath = `${basePath}/${upload_path}/${filename}`;
|
|
const cosDomain = this.config.COS_DOMAIN; // 保存this.config的引用
|
|
|
|
return new Promise((resolve, reject) => {
|
|
this.cosClient.putObject({
|
|
Bucket: this.config.COS_BUCKET,
|
|
Region: this.config.COS_REGION,
|
|
Key: `${path}/${filename}`,
|
|
StorageClass: 'STANDARD',
|
|
Body: fs.createReadStream(localFilePath),
|
|
}, function (err, data) {
|
|
fs.unlink(localFilePath, function (err) {
|
|
if (err) {
|
|
console.error('Failed to delete local file:', err);
|
|
}
|
|
});
|
|
|
|
if (err) {
|
|
reject(err);
|
|
} else {
|
|
const response = {
|
|
name: filename,
|
|
path: `${cosDomain}/${path}/${filename}`,
|
|
data: data
|
|
};
|
|
resolve(response);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 上传文件到OSS
|
|
* @param basePath 应用根路径
|
|
* @param upload_path 上传路径
|
|
* @param filename 文件名
|
|
* @returns {Promise<*>}
|
|
*/
|
|
async uploadToOSS(basePath, upload_path, filename) {
|
|
if (!this.ossClient) {
|
|
throw new Error('OSS client not initialized. Please check OSS configuration.');
|
|
}
|
|
|
|
const date = new Date();
|
|
const path = `${upload_path}/${date.getFullYear()}${date.getMonth() + 1}/${date.getDate()}`;
|
|
const fullPath = `${path}/${filename}`;
|
|
const localFilePath = `${basePath}/${upload_path}/${filename}`;
|
|
|
|
try {
|
|
const result = await this.ossClient.put(fullPath, localFilePath);
|
|
// 上传完成后删除本地文件
|
|
fs.unlink(localFilePath, function (err) {
|
|
if (err) {
|
|
console.error('Failed to delete local file:', err);
|
|
}
|
|
});
|
|
|
|
return {
|
|
name: filename,
|
|
path: result.url,
|
|
data: result
|
|
};
|
|
} catch (err) {
|
|
// 出错时也删除本地文件
|
|
fs.unlink(localFilePath, function (err) {
|
|
if (err) {
|
|
console.error('Failed to delete local file:', err);
|
|
}
|
|
});
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
|
|
export default StorageManager; |