Skip to content

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:

  • sftp
  • azure
  • s3
  • gcp

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 headers

Invariants

  • 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.py
  • tests/unit/storage/test_azure_storage.py
  • tests/unit/storage/test_virus_scan_integration.py
  • tests/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.