6.4 KiB
6.4 KiB
File Path Storage in Database - How It Works
This document explains how file paths and storage URLs are stored in the database for different storage scenarios (GCS vs Local Storage).
Database Schema
Documents Table
file_path(VARCHAR(500), NOT NULL): Stores the relative path or GCS pathstorage_url(VARCHAR(500), NULLABLE): Stores the full URL for accessing the file
Work Note Attachments Table
file_path(VARCHAR(500), NOT NULL): Stores the relative path or GCS pathstorage_url(VARCHAR(500), NULLABLE): Stores the full URL for accessing the file
Storage Scenarios
Scenario 1: File Uploaded to GCS (Successfully)
When GCS is configured and the upload succeeds:
Database Values:
file_path = "requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf"
storage_url = "https://storage.googleapis.com/bucket-name/requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf"
File Location:
- Physical: Google Cloud Storage bucket
- Path Structure:
requests/{requestNumber}/{fileType}/{fileName} - Access: Public URL or signed URL (depending on bucket configuration)
Scenario 2: File Saved to Local Storage (GCS Not Configured or Failed)
When GCS is not configured or upload fails, files are saved to local storage:
Database Values:
file_path = "requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf"
storage_url = "/uploads/requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf"
File Location:
- Physical: Local filesystem at
{UPLOAD_DIR}/requests/{requestNumber}/{fileType}/{fileName} - Path Structure: Same as GCS structure for consistency
- Access: Served via Express static middleware at
/uploads/*
Example:
uploads/
└── requests/
└── REQ-2025-12-0001/
├── documents/
│ └── 1701234567890-abc123-proposal.pdf
└── attachments/
└── 1701234567890-xyz789-note.pdf
Scenario 3: Legacy Files (Before This Implementation)
Older files may have different path formats:
Possible Database Values:
file_path = "/absolute/path/to/uploads/file.pdf" -- Absolute path
-- OR
file_path = "file.pdf" -- Simple filename (in root uploads folder)
storage_url = "/uploads/file.pdf" -- Simple URL
File Location:
- Physical: Various locations depending on when file was uploaded
- Access: Handled by legacy route logic
How Download/Preview Routes Handle Different Storage Types
Document Preview Route (GET /workflows/documents/:documentId/preview)
-
Check if GCS URL:
const isGcsUrl = storageUrl && ( storageUrl.startsWith('https://storage.googleapis.com') || storageUrl.startsWith('gs://') );- If yes → Redirect to GCS URL
-
Check if Local Storage URL:
if (storageUrl && storageUrl.startsWith('/uploads/')) { res.redirect(storageUrl); // Express static serves it return; }- If yes → Redirect to
/uploads/...(served by Express static middleware)
- If yes → Redirect to
-
Legacy File Handling:
const absolutePath = filePath && !path.isAbsolute(filePath) ? path.join(UPLOAD_DIR, filePath) : filePath;- Resolve relative path to absolute
- Serve file directly using
res.sendFile()
Work Note Attachment Routes
Same logic as document routes:
- Preview:
/workflows/work-notes/attachments/:attachmentId/preview - Download:
/workflows/work-notes/attachments/:attachmentId/download
Key Points
1. Consistent Path Structure
- Both GCS and local storage use the same path structure:
requests/{requestNumber}/{fileType}/{fileName} - This makes migration seamless when moving from local to GCS
2. Storage URL Format
- GCS: Full HTTPS URL (
https://storage.googleapis.com/...) - Local: Relative URL (
/uploads/requests/...) - Legacy: May vary
3. File Path Format
- GCS: Relative path in bucket (
requests/REQ-.../documents/file.pdf) - Local: Same relative path format for consistency
- Legacy: May be absolute path or simple filename
4. Automatic Fallback
- When GCS fails, system automatically saves to local storage
- Same folder structure maintained
- No data loss
5. Serving Files
- GCS files: Redirect to public/signed URL
- Local files (new): Redirect to
/uploads/...(Express static) - Local files (legacy): Direct file serving with
res.sendFile()
Migration Path
When migrating from local storage to GCS:
- Files already follow same structure - No path changes needed
- Upload new files - They automatically go to GCS if configured
- Existing files - Can remain in local storage until migrated
- Database - Only
storage_urlfield changes (from/uploads/...tohttps://...)
Example Database Records
GCS File (New Upload)
{
"document_id": "uuid-123",
"file_path": "requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf",
"storage_url": "https://storage.googleapis.com/my-bucket/requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf",
"file_name": "1701234567890-abc123-proposal.pdf",
"original_file_name": "proposal.pdf"
}
Local Storage File (Fallback)
{
"document_id": "uuid-456",
"file_path": "requests/REQ-2025-12-0001/documents/1701234567891-def456-report.pdf",
"storage_url": "/uploads/requests/REQ-2025-12-0001/documents/1701234567891-def456-report.pdf",
"file_name": "1701234567891-def456-report.pdf",
"original_file_name": "report.pdf"
}
Legacy File (Old Format)
{
"document_id": "uuid-789",
"file_path": "/var/app/uploads/old-file.pdf",
"storage_url": "/uploads/old-file.pdf",
"file_name": "old-file.pdf",
"original_file_name": "old-file.pdf"
}
Troubleshooting
Issue: File not found when downloading
Check:
- Verify
storage_urlformat in database - Check if file exists at expected location:
- GCS: Check bucket and path
- Local: Check
{UPLOAD_DIR}/requests/...path
- Verify Express static middleware is mounted at
/uploads
Issue: Files not organizing correctly
Check:
- Verify
requestNumberis being passed correctly to upload functions - Check folder structure matches:
requests/{requestNumber}/{fileType}/ - Verify
fileTypeis either'documents'or'attachments'