article-writer-cn
Version:
AI 驱动的智能写作系统 - 专注公众号/自媒体文章创作
145 lines • 4.54 kB
JavaScript
/**
* 阿里云 OSS 图床提供者
*
* 参考文档: https://help.aliyun.com/document_detail/111265.html
*/
import OSS from 'ali-oss';
import fs from 'fs-extra';
import path from 'path';
import crypto from 'crypto';
export class AliyunOSSProvider {
type = 'aliyun-oss';
config;
client;
constructor(config) {
this.config = config;
// 初始化 OSS 客户端
this.client = new OSS({
region: config.region,
accessKeyId: config.accessKeyId,
accessKeySecret: config.accessKeySecret,
bucket: config.bucket,
});
}
/**
* 上传单张图片到阿里云 OSS
*/
async upload(imagePath, remotePath) {
try {
// 检查文件是否存在
if (!await fs.pathExists(imagePath)) {
return {
success: false,
url: '',
originalPath: imagePath,
error: '文件不存在',
provider: this.type,
};
}
// 获取文件大小
const fileStat = await fs.stat(imagePath);
// 生成远程路径
const key = remotePath || this.generateRemotePath(imagePath);
// 上传文件
const result = await this.client.put(key, imagePath, {
headers: {
'Content-Type': this.getContentType(imagePath),
},
});
// 生成访问 URL
const url = this.buildPublicUrl(key);
return {
success: true,
url,
originalPath: imagePath,
size: fileStat.size,
provider: this.type,
};
}
catch (error) {
return {
success: false,
url: '',
originalPath: imagePath,
error: error instanceof Error ? error.message : '上传失败',
provider: this.type,
};
}
}
/**
* 批量上传图片
*/
async uploadBatch(imagePaths) {
return Promise.all(imagePaths.map(path => this.upload(path)));
}
/**
* 验证配置是否有效
*/
async validateConfig() {
try {
// 尝试列出 bucket 内容(只列出1个对象即可)
await this.client.list({
'max-keys': 1,
});
return true;
}
catch (error) {
console.error('阿里云 OSS 配置验证失败:', error);
return false;
}
}
/**
* 生成远程文件路径
* 格式: images/{year}/{month}/{hash}-{filename}
*/
generateRemotePath(localPath) {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const fileName = path.basename(localPath);
const ext = path.extname(fileName);
const nameWithoutExt = path.basename(fileName, ext);
// 生成 8 位哈希
const hash = crypto
.createHash('md5')
.update(localPath + Date.now())
.digest('hex')
.slice(0, 8);
return `images/${year}/${month}/${nameWithoutExt}-${hash}${ext}`;
}
/**
* 根据文件扩展名确定 Content-Type
*/
getContentType(filePath) {
const ext = path.extname(filePath).toLowerCase();
const contentTypes = {
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.webp': 'image/webp',
'.svg': 'image/svg+xml',
};
return contentTypes[ext] || 'application/octet-stream';
}
/**
* 构建公开访问 URL
*/
buildPublicUrl(key) {
if (this.config.customDomain) {
// 使用自定义域名
let domain = this.config.customDomain;
if (!domain.startsWith('http://') && !domain.startsWith('https://')) {
domain = `https://${domain}`;
}
domain = domain.replace(/\/$/, '');
return `${domain}/${key}`;
}
else {
// 使用默认域名
// 格式: https://{bucket}.{region}.aliyuncs.com/{key}
return `https://${this.config.bucket}.${this.config.region}.aliyuncs.com/${key}`;
}
}
}
//# sourceMappingURL=aliyun-oss-provider.js.map