import { Controller, Get, Delete, Query, HttpCode, HttpStatus, Res, StreamableFile, } from '@nestjs/common'; import type { Response } from 'express'; import { ApiTags, ApiOperation, ApiQuery } from '@nestjs/swagger'; import { BackblazeStorageService } from './backblaze-storage.service'; import { FileType } from './enums/file-type.enum'; import { LogToDiscord } from 'src/shared/decorators/log-to-discord.decorator'; @ApiTags('Upload: Backblaze B2 Storage') @Controller('backblaze') @LogToDiscord() export class BackblazeStorageController { constructor( private readonly backblazeStorageService: BackblazeStorageService, ) {} @Get('presigned-upload') @ApiOperation({ summary: 'Get presigned upload URL' }) @ApiQuery({ name: 'fileName', required: true }) @ApiQuery({ name: 'fileType', enum: FileType, required: false }) async getPresignedUploadUrl( @Query('fileName') fileName: string, @Query('fileType') fileType?: FileType, ) { return this.backblazeStorageService.getPresignedUploadUrl( fileName, fileType, ); } @Get('resize') @ApiOperation({ summary: 'Resize and serve image from B2' }) @ApiQuery({ name: 'path', required: true, description: 'File path in B2' }) @ApiQuery({ name: 'w', required: false, description: 'Width in pixels' }) @ApiQuery({ name: 'h', required: false, description: 'Height in pixels' }) @ApiQuery({ name: 'q', required: false, description: 'Quality (1-100)', type: Number, }) async resizeImage( @Res({ passthrough: true }) res: Response, @Query('path') path: string, @Query('w') width?: string, @Query('h') height?: string, @Query('q') quality?: string, ): Promise { const result = await this.backblazeStorageService.resizeImage( path, width ? parseInt(width) : undefined, height ? parseInt(height) : undefined, quality ? parseInt(quality) : undefined, ); res.set({ 'Content-Type': result.contentType, 'Cache-Control': 'public, max-age=31536000', // Cache for 1 year }); return new StreamableFile(result.buffer); } @Delete('by-url') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Delete file by CDN URL' }) async deleteFileByUrl(@Query('url') url: string) { const result = await this.backblazeStorageService.deleteFileByUrl(url); return { message: 'File deleted successfully', ...result, }; } }