appointment_system/backend/UPLOAD_FEATURE.md
2025-12-11 22:50:18 +08:00

6.2 KiB

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):

{
  "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
    {
      "success": false,
      "error": {
        "code": "NO_FILE",
        "message": "No file uploaded"
      }
    }
    
  • 500 Internal Server Error - Invalid file type or processing error

Configuration

Environment Variables

# 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

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

curl -X POST http://localhost:3000/api/v1/upload/image \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "image=@/path/to/image.jpg"

Axios

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