File management and serving
File management and serving
File handling is split into two halves:
- request-time upload and persistence
- authenticated serving and preview delivery
The implementation spans api/views/file_management_views/upload_views.py, api/views/file_serving_views/cache_jwt_views.py, and api/services/storage/*.
Upload path
FileUploadAPIView validates an uploaded file, computes a hash for deduplication, writes the file to storage, generates preview metadata, and persists a UserUploadedFile row.
Important behavior:
- only authenticated users with consent can upload
- the user/tenant context is captured on the database row
- duplicate uploads are short-circuited by matching the file hash for the same user
- preview text and page counts are stored when available
- event logging records both success and failure
Serving path
JWTFileServeView is the general-purpose authenticated file-serving view. It accepts JWT-compatible auth and can return:
- a JSON file-info payload
- an inline or attachment response for the raw file
- a redirect to an external URL when the storage backend returns one
ProcessedFileImageView / serve_processed_file_image is the preview-oriented path for processed-file images. It is decorated to work in browser frames and adds cache headers for the image response.
Storage abstraction
api/services/storage/storage_factory.py is the selection layer for file storage providers. It creates one of four backends based on STORAGE_TYPE:
sftpazures3gcp
The factory caches created instances and can validate backend-specific environment variables.
File-serving flow
sequenceDiagram participant Client participant Upload as FileUploadAPIView participant Factory as StorageFactory participant Backend as Storage backend participant Serve as JWTFileServeView participant Preview as ProcessedFileImageView
Client->>Upload: POST file Upload->>Factory: choose storage provider Factory->>Backend: store file / get link Upload->>Upload: hash, preview, UserUploadedFile row Client->>Serve: GET file by id Serve->>Backend: resolve file path / URL Serve-->>Client: file bytes or redirect Client->>Preview: GET processed preview Preview-->>Client: inline image with cache headersInvariants
- storage selection is environment-driven and cached
- upload dedupe is per user and file hash
- file serving must enforce ownership/authorization before exposing content
- preview and raw file endpoints are distinct because browsers and API consumers need different response shapes
Validation
tests/integration/test_file_management.pytests/unit/storage/test_azure_storage.pytests/unit/storage/test_virus_scan_integration.pytests/unit/misc/test_upload_config.py
Scope boundary
This page covers file upload and delivery. For the document-processing upload endpoint that creates a processing job instead of a stored file record, read Document upload and validation.