ERPTurbo_Poster/lib/storage.js
2025-11-14 14:18:32 +08:00

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;