fix: harden real backend workflows and channel connections

This commit is contained in:
hectorzhao
2026-07-06 17:54:53 +08:00
parent 8cca361441
commit b5132d7f4e
47 changed files with 2530 additions and 314 deletions
+20 -1
View File
@@ -1,4 +1,4 @@
import { Body, Controller, Get, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { BadRequestException, Body, Controller, Get, Param, Post, Query, Res, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { ApiTags } from '@nestjs/swagger';
import { TenantId } from '../common/tenant-id.decorator';
@@ -11,6 +11,11 @@ type UploadedMultipartFile = {
buffer: Buffer;
};
type DownloadResponse = {
setHeader(name: string, value: number | string): void;
send(content: Buffer): void;
};
@ApiTags('files')
@Controller('admin/files')
export class FilesController {
@@ -21,6 +26,17 @@ export class FilesController {
return this.files.list(tenantId);
}
@Get(':id/download')
async download(@Param('id') id: string, @Query('disposition') disposition: string | undefined, @Res() response: DownloadResponse) {
const { fileObject, content } = await this.files.getDownload(id);
const mode = disposition === 'inline' ? 'inline' : 'attachment';
const encodedName = encodeURIComponent(fileObject.fileName);
response.setHeader('Content-Type', fileObject.contentType || 'application/octet-stream');
response.setHeader('Content-Length', content.length);
response.setHeader('Content-Disposition', `${mode}; filename*=UTF-8''${encodedName}`);
response.send(content);
}
@Post()
create(@Body() body: CreateFileObjectDto) {
return this.files.create(body);
@@ -34,6 +50,9 @@ export class FilesController {
@Post('upload')
@UseInterceptors(FileInterceptor('file', { limits: { fileSize: 20 * 1024 * 1024 } }))
upload(@UploadedFile() file: UploadedMultipartFile, @Body('purpose') purpose: string, @Body('prefix') prefix?: string, @TenantId() tenantId?: string) {
if (!file) {
throw new BadRequestException('Upload file is required');
}
return this.files.upload({ tenantId, purpose: purpose || 'general', prefix }, file);
}
}