Testing & Deployment
In this final section, you'll thoroughly test your complete file storage system and deploy it to production. You'll also learn how to troubleshoot common issues and optimize your setup.
What We'll Test
Your complete file storage system includes:
- Basic file operations - Upload, download, delete, list
- Pre-signed URLs - Secure, temporary file access
- CORS configuration - Proper cross-origin access
- Security - Credential management and access controls
Prerequisites
Before starting, ensure you have completed:
- R2 Bucket Setup - Bucket created and configured
- File Operations - Basic CRUD operations implemented
- Advanced Security - Pre-signed URLs implemented
- All environment variables set as secrets
Verify Your Setup
# Navigate to your backend project
cd ~/projects/blazenote-backend
# Check that all required files exist
ls src/routes/files*.ts
# Should show: files.route.ts files-workers.route.ts
# Verify environment variables are set
wrangler secret list
# Should show: R2_ACCESS_KEY, R2_SECRET_KEY, R2_ENDPOINT, R2_BUCKET_NAME
Step 1: Test Local Development
Start Development Server
Start your development server:
npm run dev
Expected output:
⎔ Starting local server...
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
[wrangler:inf] Ready on http://localhost:8787
Test Basic File Operations
Test file upload:
# Test direct upload (replace with actual file path)
curl -X POST http://localhost:8787/files-workers/upload \
-F "file=@/path/to/test-image.jpg"
Expected response:
{
"success": true,
"message": "File uploaded successfully",
"filename": "1234567890-test-image.jpg"
}
Test file listing:
curl http://localhost:8787/files-workers/list
Expected response:
{
"success": true,
"keys": ["1234567890-test-image.jpg"]
}
Test file download:
# Replace with actual filename from upload
curl http://localhost:8787/files-workers/1234567890-test-image.jpg \
--output downloaded-file.jpg
Test file deletion:
# Replace with actual filename
curl -X DELETE http://localhost:8787/files-workers/1234567890-test-image.jpg
Test Pre-signed URLs
Test upload pre-signed URL generation:
curl -X POST http://localhost:8787/files/pre-signed-url \
-H "Content-Type: application/json" \
-d '{"fileName": "presigned-test.jpg"}'
Expected response:
{
"key": "1234567890-presigned-test.jpg",
"url": "https://blazenote.r2.cloudflarestorage.com/1234567890-presigned-test.jpg?X-Amz-Algorithm=..."
}
Test download pre-signed URL generation:
# Replace with actual filename
curl http://localhost:8787/files/pre-signed-url/1234567890-presigned-test.jpg
Verify in R2 Dashboard
Check uploaded files:
- Go to Cloudflare Dashboard
- Navigate to R2 Object Storage → Your bucket
- You should see your uploaded test files
- Click on a file to view its details and metadata
[ PLACEHOLDER: Add screenshot showing files in R2 dashboard ] -->
Step 2: Test Production Deployment
Deploy to Production
Deploy your backend with all file functionality:
npm run deploy
Expected output:
⎔ Starting deployment...
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Successfully deployed to workers.dev
Successfully deployed to custom domain
After successful deployment, navigate to your frontend URL to test the application. You can create notes and attach files to them using the interface. Note that the application doesn't display a progress indicator during file uploads - you'll need to refresh the page after uploading to verify that your files have been properly attached.
Optionally, you can proceed with testing the production endpoints as listed below.
Test Production Endpoints
Test production file operations:
# Replace with your actual backend domain
curl https://api.yourname.com/files-workers/list
Expected response:
{ "success": true, "keys": [] }
Test production pre-signed URL generation:
# Replace with your actual backend domain
curl -X POST https://api.yourname.com/files/pre-signed-url \
-H "Content-Type: application/json" \
-d '{"fileName": "production-test.jpg"}'
Step 3: Performance Testing
Test File Upload Performance
Test with different file sizes:
# Small file (< 1MB)
curl -X POST http://localhost:8787/files-workers/upload \
-F "file=@small-file.jpg" \
-w "Time: %{time_total}s\n"
# Medium file (1-5MB)
curl -X POST http://localhost:8787/files-workers/upload \
-F "file=@medium-file.jpg" \
-w "Time: %{time_total}s\n"
# Large file (5-10MB)
curl -X POST http://localhost:8787/files-workers/upload \
-F "file=@large-file.jpg" \
-w "Time: %{time_total}s\n"
Test Pre-signed URL Performance
Compare direct upload vs pre-signed URL:
# Time direct upload
time curl -X POST http://localhost:8787/files-workers/upload \
-F "file=@test-file.jpg"
# Time pre-signed URL generation + upload
time curl -X POST http://localhost:8787/files/pre-signed-url \
-H "Content-Type: application/json" \
-d '{"fileName": "test-file.jpg"}'
Troubleshooting
Common Issues and Solutions
"Access denied" errors:
- Check CORS policy includes your domain
- Verify R2_ACCESS_KEY and R2_SECRET_KEY are set as secrets
- Ensure API token has R2:Edit permissions
- Confirm R2_ENDPOINT is correct
Files not uploading:
- Check file size limits (Workers have 100MB limit)
- Verify content type is set correctly
- Check network tab for CORS errors
- Ensure bucket binding is configured
Pre-signed URLs not working:
- Verify all environment variables are set
- Check AWS SDK is installed correctly
- Ensure bucket name matches everywhere
- Test with shorter expiry times first
Performance issues:
- Use pre-signed URLs for large files
- Implement file compression
- Add file type validation
- Consider file size limits
Debug Commands
Check environment variables:
wrangler secret list
Check bucket configuration:
wrangler r2 bucket list
Check CORS policy:
# View bucket details in dashboard
wrangler r2 bucket info blazenote
Test bucket access:
# List objects in bucket
wrangler r2 object list blazenote
Performance Optimization
Best Practices
File Upload Optimization:
- Use pre-signed URLs for files > 1MB
- Implement client-side file validation
- Add progress indicators for large uploads
- Consider chunked uploads for very large files
Security Optimization:
- Set appropriate expiry times for pre-signed URLs
- Implement file type validation
- Add rate limiting on URL generation
- Log file operations for auditing
Storage Optimization:
- Implement file cleanup for temporary files
- Add lifecycle policies for old files
- Monitor storage usage and costs
- Consider file compression for documents
Summary
🎉 Congratulations! You've successfully built and deployed a complete file storage system with Cloudflare R2. Here's what you've accomplished:
What You Built
- R2 Bucket - Secure, scalable file storage
- Basic File Operations - Upload, download, delete, list
- Advanced Security - Pre-signed URLs for secure access
- CORS Configuration - Proper cross-origin access controls
- Environment Management - Secure credential handling
- Production Deployment - Fully functional in production
- Testing Suite - Comprehensive testing procedures
Key Benefits Achieved
- Zero egress fees - No charges for file downloads
- Global performance - Files cached worldwide
- Enterprise security - Temporary access controls
- S3 compatibility - Easy integration and migration
- Scalable architecture - Handles growing file volumes
Performance Metrics
- Direct uploads - Good for small files (< 1MB)
- Pre-signed URLs - Optimal for larger files (> 1MB)
- Global CDN - Fast access from anywhere
- High availability - Built on Cloudflare's network
Next Steps
With your file storage system complete, you can:
- Integrate with frontend - Add file uploads to your note-taking app
- Add file previews - Display images and documents in your UI
- Implement file organization - Add folders and categories
- Add file sharing - Generate shareable links
- Monitor usage - Track storage costs and performance
Your note-taking application now has professional-grade file storage capabilities that can scale with your users! 🚀