76 lines
2.0 KiB
TypeScript
76 lines
2.0 KiB
TypeScript
|
|
import { Injectable, BadRequestException } from '@nestjs/common';
|
|||
|
|
import { ConfigService } from '@nestjs/config';
|
|||
|
|
import * as fs from 'fs';
|
|||
|
|
import * as path from 'path';
|
|||
|
|
import { randomBytes } from 'crypto';
|
|||
|
|
|
|||
|
|
@Injectable()
|
|||
|
|
export class UploadService {
|
|||
|
|
private readonly uploadDir: string;
|
|||
|
|
|
|||
|
|
constructor(private configService: ConfigService) {
|
|||
|
|
// 上传文件存储目录
|
|||
|
|
this.uploadDir = path.join(process.cwd(), 'uploads');
|
|||
|
|
|
|||
|
|
// 确保上传目录存在
|
|||
|
|
if (!fs.existsSync(this.uploadDir)) {
|
|||
|
|
fs.mkdirSync(this.uploadDir, { recursive: true });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async uploadFile(
|
|||
|
|
file: Express.Multer.File,
|
|||
|
|
tenantId?: number,
|
|||
|
|
userId?: number,
|
|||
|
|
): Promise<{ url: string; fileName: string; size: number }> {
|
|||
|
|
if (!file) {
|
|||
|
|
throw new BadRequestException('文件不存在');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生成唯一文件名
|
|||
|
|
const fileExt = path.extname(file.originalname);
|
|||
|
|
const uniqueId = randomBytes(16).toString('hex');
|
|||
|
|
const fileName = `${uniqueId}${fileExt}`;
|
|||
|
|
|
|||
|
|
// 根据租户ID和用户ID创建目录结构:uploads/tenantId/userId/
|
|||
|
|
let targetDir = this.uploadDir;
|
|||
|
|
if (tenantId) {
|
|||
|
|
targetDir = path.join(targetDir, `tenant_${tenantId}`);
|
|||
|
|
if (!fs.existsSync(targetDir)) {
|
|||
|
|
fs.mkdirSync(targetDir, { recursive: true });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (userId) {
|
|||
|
|
targetDir = path.join(targetDir, `user_${userId}`);
|
|||
|
|
if (!fs.existsSync(targetDir)) {
|
|||
|
|
fs.mkdirSync(targetDir, { recursive: true });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 文件保存路径
|
|||
|
|
const filePath = path.join(targetDir, fileName);
|
|||
|
|
|
|||
|
|
// 保存文件
|
|||
|
|
fs.writeFileSync(filePath, file.buffer);
|
|||
|
|
|
|||
|
|
// 生成访问URL
|
|||
|
|
// 格式:/api/uploads/tenantId/userId/fileName 或 /api/uploads/fileName
|
|||
|
|
let urlPath = '/api/uploads';
|
|||
|
|
if (tenantId) {
|
|||
|
|
urlPath += `/tenant_${tenantId}`;
|
|||
|
|
if (userId) {
|
|||
|
|
urlPath += `/user_${userId}`;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
urlPath += `/${fileName}`;
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
url: urlPath,
|
|||
|
|
fileName: file.originalname,
|
|||
|
|
size: file.size,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|