Spaces:
Sleeping
Cloudinary Image Upload Integration Guide - SwiftOps Backend
Overview
This document outlines the integration of Cloudinary for image management in the SwiftOps backend. Our backend will handle image uploads from users, store them in organized Cloudinary folders, wait for the upload to complete and receive the URL, then update our Supabase database with the returned URL.
Architecture Flow
User submits image β FastAPI receives file β Upload to Cloudinary β Receive URL β Update Supabase documents table
Understanding Cloudinary Folder Modes
Cloudinary accounts created after June 4th, 2024 use "dynamic folder mode" by default, which separates the folder organization (where files appear in the Media Library) from the public_id (the URL path used for delivery).
Key Concepts
Dynamic Folder Mode (Modern Approach)
- The
asset_folderparameter controls where files appear in the Cloudinary Media Library - The
public_idparameter controls the URL path for accessing the file - These two can be different or the same, giving you flexibility
- You can use
public_id_prefixto prepend a path to the public_id with a forward slash for SEO purposes
Legacy Fixed Folder Mode (Older Accounts)
- The
folderparameter sets both the public ID path and the folder placement of the asset - Simpler but less flexible
Our Folder Structure
We will organize uploads into three main categories:
/swiftops/tickets/ - Work order photos, site images, equipment photos
/swiftops/users/ - User profile avatars and related images
/swiftops/receipts/ - Payment receipts, expense documents, invoices
How Upload Parameters Work
For Dynamic Folder Mode Accounts (Post-June 2024)
When uploading a file, you should use:
asset_folder- Sets where the file appears in your Cloudinary Media Library for organizationpublic_id- Sets the unique identifier and URL path for the fileuse_filename- Boolean to use the original filenameunique_filename- Boolean to generate unique names (prevents collisions)overwrite- Boolean to replace existing files with same public_id
For Legacy Fixed Folder Mode Accounts (Pre-June 2024)
Use the folder parameter which handles both organization and URL path.
Upload Response Structure
When you upload a file, Cloudinary returns a response containing the secure URL, public ID, format, dimensions, file size, and creation timestamp.
The key information we need for our database:
secure_url- The HTTPS URL to access the image (this goes to Supabase)public_id- The unique identifier (for future updates/deletions)format- File format (jpg, png, etc.)bytes- File sizewidth/height- Image dimensionscreated_at- Upload timestamp
Database Integration
Documents Table Structure
Our documents table in Supabase will store:
id- UUID primary keyentity_type- Type of entity (ticket, user, receipt)entity_id- Foreign key to the related entitydocument_url- The Cloudinary secure_url goes herecloudinary_public_id- For managing the asset laterfile_name- Original filenamefile_type- MIME typefile_size- Size in bytesuploaded_by- User who uploadedcreated_at- Timestamp
Workflow Steps
- Receive file upload from user via FastAPI endpoint
- Validate file (check type, size limits, etc.)
- Upload to Cloudinary using appropriate folder:
- Tickets β
/swiftops/tickets/ - Users β
/swiftops/users/ - Receipts β
/swiftops/receipts/
- Tickets β
- Wait for Cloudinary response (this is synchronous - the upload method waits)
- Extract the
secure_urlfrom response - Insert record into documents table with:
- The Cloudinary URL
- Entity information (what this image is for)
- File metadata
- Upload details
- Return success response to user with the document ID
Error Handling Considerations
Upload Failures
If Cloudinary upload fails:
- Return appropriate error to user
- Log the error details
- Do NOT create database record
Database Failures
If Supabase insert fails after successful upload:
- Consider deleting the uploaded image from Cloudinary (cleanup)
- Return error to user
- Log for manual review
Partial Failures
- Transaction-like behavior: Either both succeed or both fail
- Prevents orphaned files in Cloudinary
- Prevents broken URL references in database
Upload Presets
Upload presets can be configured in your Cloudinary dashboard to establish naming and storage conventions for specific types of assets.
Recommended Preset Configuration
For each asset type (tickets, users, receipts), create a preset with:
- Signing mode:
Signed(more secure for backend uploads) - Asset folder: Set to appropriate folder path
- Generated public ID:
Auto-generate an unguessable public ID value(prevents conflicts) - Overwrite: Based on your use case (usually OFF for tickets, ON for user avatars)
Benefits of using presets:
- Centralized configuration
- Consistent naming conventions
- Easier to update behavior across all uploads
- Can set transformation defaults (resize, format, quality)
File Size and Type Considerations
Size Limits
- Files under 100 MB can use the standard upload method
- Files larger than 100 MB require the
upload_largemethod, which uploads in chunks for better reliability - Consider setting application-level limits (e.g., 10 MB for receipts, 5 MB for avatars)
Supported Formats
- Cloudinary can upload any file type, not just images and videos
- For our use case: JPEG, PNG, PDF (for receipts), WebP
- Set
resource_type="auto"to let Cloudinary detect the type
Security Considerations
API Credentials
- Never expose your Cloudinary credentials in client-side code
- Use environment variables for
CLOUDINARY_CLOUD_NAME,CLOUDINARY_API_KEY,CLOUDINARY_API_SECRET - Backend-only uploads using signed requests
Access Control
- All uploads go through authenticated FastAPI endpoints
- Verify user permissions before allowing uploads
- Validate file types and sizes server-side
URL Security
- Cloudinary URLs are public by default (anyone with URL can access)
- For sensitive documents, consider using Cloudinary's authenticated delivery
- Store URLs in database with appropriate access control
Performance Optimization
Upload Speed
- Cloudinary automatically optimizes upload routes
- Files are uploaded to nearest data center
- Response time typically 1-3 seconds for standard images
Delivery Optimization
- Cloudinary provides automatic image optimization and transformation capabilities
- URLs can include transformation parameters for on-the-fly resizing
- Example:
w_300,h_300,c_fillin URL for thumbnail generation - CDN delivery for fast global access
Monitoring and Maintenance
What to Track
- Upload success/failure rates
- Average upload times
- Storage usage by folder
- Failed uploads requiring retry
Cleanup Strategy
- Implement soft deletes in database
- Keep Cloudinary images even if database record is deleted (for audit trail)
- Scheduled cleanup jobs for truly orphaned files
- Use Admin API methods to list, search, and manage assets
Testing Considerations
Local Development
- Use test/development folder structure:
/swiftops-dev/tickets/ - Separate Cloudinary account or folder for testing
- Mock Cloudinary responses for unit tests
Staging Environment
- Mirror production folder structure
- Test with various file types and sizes
- Verify error handling paths
- Test concurrent uploads
Common Pitfalls to Avoid
- Not waiting for upload completion - The Python SDK upload method is synchronous and waits, but ensure you handle it properly
- Not storing public_id - You'll need this for updates or deletions
- Using wrong folder parameter - Check if your account is dynamic or fixed folder mode
- Not validating files - Always validate on backend, never trust client validation alone
- Forgetting error handling - Network issues, quota limits, invalid files all need handling
- Not setting resource limits - Can lead to quota exhaustion or large bills
Next Steps for Implementation
- Get Cloudinary credentials from dashboard (Settings β API Keys)
- Install Python SDK (
pip install cloudinary) - Configure environment variables in your
.envfile - Create upload presets in Cloudinary dashboard for each folder
- Set up Supabase documents table with proper schema
- Implement upload endpoints in FastAPI
- Add error handling and validation
- Test thoroughly with various file types and error scenarios
- Deploy to staging and verify in production-like environment
- Monitor uploads and optimize based on real usage
Additional Resources
- Cloudinary Upload Guide provides comprehensive details and examples of upload options
- Python image and video upload documentation covers common usage patterns
- Folder modes documentation explains the differences between dynamic and fixed folder modes
This document should be updated as implementation details are finalized and new requirements emerge.