Skip to content

Issue #91: Backend — File Upload Service (Cloudinary) #244

@wumibals

Description

@wumibals

Labels: backend upload cloudinary nestjs
Area: backend/src/modules/upload/upload.service.ts, backend/src/modules/upload/upload.controller.ts, backend/src/modules/upload/upload.module.ts
Difficulty: Intermediate

Description

Gallery images, menu item photos, and Instagram post images are uploaded to Cloudinary. This module provides a single POST /upload endpoint that accepts a multipart/form-data file, uploads it to Cloudinary, and returns the secure URL.

Acceptance Criteria

  • Install and configure cloudinary v2 npm package
  • Create backend/src/modules/upload/upload.service.ts with UploadService:
    • Constructor reads Cloudinary credentials from ConfigService (cloudinary.cloudName, cloudinary.apiKey, cloudinary.apiSecret) and calls v2.config()
    • uploadImage(file: Express.Multer.File, folder?: string): Promise<{ url: string; publicId: string }> — uploads the buffer using v2.uploader.upload_stream, resolves with { url: result.secure_url, publicId: result.public_id }
    • deleteImage(publicId: string): Promise<void> — calls v2.uploader.destroy(publicId)
  • Create backend/src/modules/upload/upload.controller.ts with @Controller('upload'):
    • POST /upload@UseGuards(JwtAuthGuard), @UseInterceptors(FileInterceptor("file")), validates file is an image (MIME check), max size 5 MB, calls uploadImage; returns { url, publicId }
    • DELETE /upload/:publicId@UseGuards(JwtAuthGuard), URL-decodes publicId, calls deleteImage
  • Create backend/src/modules/upload/upload.module.ts — imports MulterModule.register({ storage: memoryStorage() }), ConfigModule; exports UploadService
  • Reject non-image MIME types with BadRequestException before uploading

Technical Notes

  • Use memoryStorage (not disk storage) so the file buffer is passed directly to Cloudinary without temp files
  • Cloudinary folder defaults to "thelighted" if not provided

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions