You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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 }
Labels:
backenduploadcloudinarynestjsArea:
backend/src/modules/upload/upload.service.ts,backend/src/modules/upload/upload.controller.ts,backend/src/modules/upload/upload.module.tsDifficulty: Intermediate
Description
Gallery images, menu item photos, and Instagram post images are uploaded to Cloudinary. This module provides a single
POST /uploadendpoint that accepts amultipart/form-datafile, uploads it to Cloudinary, and returns the secure URL.Acceptance Criteria
cloudinaryv2 npm packagebackend/src/modules/upload/upload.service.tswithUploadService:ConfigService(cloudinary.cloudName,cloudinary.apiKey,cloudinary.apiSecret) and callsv2.config()uploadImage(file: Express.Multer.File, folder?: string): Promise<{ url: string; publicId: string }>— uploads the buffer usingv2.uploader.upload_stream, resolves with{ url: result.secure_url, publicId: result.public_id }deleteImage(publicId: string): Promise<void>— callsv2.uploader.destroy(publicId)backend/src/modules/upload/upload.controller.tswith@Controller('upload'):POST /upload—@UseGuards(JwtAuthGuard),@UseInterceptors(FileInterceptor("file")), validates file is an image (MIME check), max size 5 MB, callsuploadImage; returns{ url, publicId }DELETE /upload/:publicId—@UseGuards(JwtAuthGuard), URL-decodespublicId, callsdeleteImagebackend/src/modules/upload/upload.module.ts— importsMulterModule.register({ storage: memoryStorage() }),ConfigModule; exportsUploadServiceBadRequestExceptionbefore uploadingTechnical Notes
memoryStorage(not disk storage) so the file buffer is passed directly to Cloudinary without temp files"thelighted"if not provided