69 lines
2.3 KiB
TypeScript
69 lines
2.3 KiB
TypeScript
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';
|
|
import { CreateFileObjectDto, CreatePresignedUploadDto, FilesService } from './files.service';
|
|
|
|
type UploadedMultipartFile = {
|
|
originalname: string;
|
|
mimetype: string;
|
|
size: number;
|
|
buffer: Buffer;
|
|
};
|
|
|
|
type DownloadResponse = {
|
|
setHeader(name: string, value: number | string): void;
|
|
send(content: Buffer): void;
|
|
};
|
|
|
|
@ApiTags('files')
|
|
@Controller('admin/files')
|
|
export class FilesController {
|
|
constructor(private readonly files: FilesService) {}
|
|
|
|
@Get()
|
|
list(@TenantId() tenantId?: string) {
|
|
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);
|
|
}
|
|
|
|
@Post('presigned-upload')
|
|
createPresignedUpload(@Body() body: CreatePresignedUploadDto) {
|
|
return this.files.createPresignedUpload(body);
|
|
}
|
|
|
|
@Post('upload')
|
|
@UseInterceptors(FileInterceptor('file', {
|
|
limits: {
|
|
fileSize: 20 * 1024 * 1024,
|
|
files: 1,
|
|
fields: 4,
|
|
parts: 5,
|
|
fieldNameSize: 100,
|
|
fieldSize: 1024,
|
|
headerPairs: 100,
|
|
},
|
|
}))
|
|
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);
|
|
}
|
|
}
|