# File Upload Feature Documentation ## Overview The file upload feature allows authenticated users to upload images to the system. Images are automatically processed, compressed, and converted to JPEG format for optimal web performance. ## Components ### 1. Upload Middleware (`src/middleware/upload.js`) - Configures Multer for handling multipart/form-data - Implements file type validation (JPEG, PNG, GIF, WebP only) - Enforces file size limits (5MB default) - Generates unique filenames using UUID and timestamp - Creates upload directory if it doesn't exist ### 2. Upload Controller (`src/controllers/uploadController.js`) - Handles image upload requests - Processes images using Sharp library: - Resizes to max 1200x1200 pixels (maintains aspect ratio) - Converts to JPEG format with 85% quality - Uses progressive JPEG encoding - Cleans up original files after processing - Returns image URL and metadata ### 3. Upload Routes (`src/routes/uploadRoutes.js`) - POST `/api/v1/upload/image` - Upload and process an image - Requires authentication (JWT token) - Accepts single file with field name 'image' ### 4. Static File Serving - Uploaded files are served from `/uploads` endpoint - Configured in `app.js` using Express static middleware ## API Endpoint ### POST /api/v1/upload/image **Authentication:** Required (Bearer token) **Request:** - Content-Type: multipart/form-data - Field name: `image` - Accepted formats: JPEG, PNG, GIF, WebP - Max file size: 5MB (configurable via `MAX_FILE_SIZE` env variable) **Success Response (200):** ```json { "success": true, "data": { "url": "/uploads/uuid-timestamp.jpg", "filename": "uuid-timestamp.jpg", "originalName": "original-filename.png", "size": 12345 } } ``` **Error Responses:** - **401 Unauthorized** - Missing or invalid authentication token - **400 Bad Request** - No file uploaded ```json { "success": false, "error": { "code": "NO_FILE", "message": "No file uploaded" } } ``` - **500 Internal Server Error** - Invalid file type or processing error ## Configuration ### Environment Variables ```env # Upload directory path (relative or absolute) UPLOAD_PATH=./uploads # Maximum file size in bytes (default: 5MB) MAX_FILE_SIZE=5242880 ``` ### File Processing Settings Located in `src/controllers/uploadController.js`: - Max dimensions: 1200x1200 pixels - JPEG quality: 85% - Progressive encoding: enabled - Fit mode: inside (maintains aspect ratio, no enlargement) ## Security Features 1. **Authentication Required** - All upload requests must include valid JWT token 2. **File Type Validation** - Only image files (JPEG, PNG, GIF, WebP) are accepted 3. **File Size Limits** - Configurable maximum file size (default 5MB) 4. **Unique Filenames** - UUID-based naming prevents overwrites and conflicts 5. **Input Sanitization** - File extensions and paths are validated ## Image Processing ### Automatic Optimizations - **Resizing**: Images larger than 1200x1200 are automatically resized - **Format Conversion**: All images are converted to JPEG for consistency - **Compression**: 85% quality JPEG compression reduces file size - **Progressive Loading**: Progressive JPEG encoding improves perceived load time ### Processing Flow 1. File uploaded via Multer middleware 2. Original file saved to upload directory 3. Sharp processes the image: - Resize if needed - Convert to JPEG - Apply compression 4. Processed file saved with .jpg extension 5. Original file deleted (if different from processed) 6. URL returned to client ## Usage Examples ### JavaScript/Fetch ```javascript const formData = new FormData(); formData.append('image', fileInput.files[0]); const response = await fetch('http://localhost:3000/api/v1/upload/image', { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, body: formData }); const result = await response.json(); console.log('Image URL:', result.data.url); ``` ### cURL ```bash curl -X POST http://localhost:3000/api/v1/upload/image \ -H "Authorization: Bearer YOUR_TOKEN" \ -F "image=@/path/to/image.jpg" ``` ### Axios ```javascript const formData = new FormData(); formData.append('image', file); const response = await axios.post('/api/v1/upload/image', formData, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'multipart/form-data' } }); console.log('Image URL:', response.data.data.url); ``` ## Testing ### Unit Tests Located in `src/tests/upload.test.js`: - Authentication validation - Middleware configuration - Controller exports ### Manual Testing See `src/tests/upload-manual-test.md` for detailed manual testing guide. ## Requirements Validation This implementation satisfies the following requirements: **Requirement 2.2**: Service creation requires image field - Provides image upload endpoint for service images - Validates and processes uploaded images **Requirement 5.2**: Withdrawal supports payment methods with details - Can be used to upload payment method verification documents - Supports various image formats for payment receipts ## File Structure ``` backend/ ├── src/ │ ├── middleware/ │ │ └── upload.js # Multer configuration │ ├── controllers/ │ │ └── uploadController.js # Upload handling logic │ ├── routes/ │ │ └── uploadRoutes.js # Upload API routes │ ├── tests/ │ │ ├── upload.test.js # Unit tests │ │ └── upload-manual-test.md # Manual testing guide │ └── app.js # Route integration ├── uploads/ # Upload directory (created automatically) └── UPLOAD_FEATURE.md # This documentation ``` ## Maintenance Notes ### Cleanup - Uploaded files are not automatically deleted - Consider implementing a cleanup job for old/unused files - Monitor disk space usage in production ### Scaling Considerations - For high-traffic applications, consider using cloud storage (S3, GCS) - Implement CDN for serving uploaded images - Add image caching headers for better performance ### Future Enhancements - Multiple file upload support - Image cropping/editing capabilities - Thumbnail generation - Different size variants (small, medium, large) - Image metadata extraction (EXIF data) - Virus scanning for uploaded files