Skip to content

The Add Files API Flow

abhishekmg edited this page Jul 2, 2025 · 1 revision

File Upload Process Documentation

This document explains the complete file upload process for the Recollect web app, including client-side and server-side logic, thumbnail handling for videos, and the new JSON-based API structure.


Overview

The file upload flow is designed to:

  • Handle large files efficiently (bypassing Vercel's 4.5MB serverless limit)
  • Support video thumbnail generation and upload
  • Use a clean, modern JSON API (no form data)
  • Store files and thumbnails in Supabase Storage

1. Client-Side Flow

a. File Selection & Preprocessing

  • User selects one or more files to upload.
  • For video files, a thumbnail is generated using the first frame.

b. React Query Optimistic Updates

  • The useFileUploadOptimisticMutation hook handles the upload process with optimistic updates.
  • Optimistic Update: Immediately adds a placeholder entry to the UI with the file name and current timestamp.
  • File Upload: Uses Supabase signed URLs to upload the file directly to storage (bypassing Vercel's 4.5MB limit).
  • Thumbnail Upload: If it's a video, uploads the thumbnail to a location.
  • Error Handling: If upload fails, the optimistic update is rolled back.

c. Uploading to Supabase Storage

  • The main file is uploaded directly to Supabase Storage using a signed URL (client-side, to avoid serverless size limits).
  • If the file is a video, the generated thumbnail (as a PNG) is also uploaded to a temporary location in Supabase Storage:
    public/{userId}/thumbnail-{uploadFileNamePath}.png

d. Sending Metadata to the API

  • After upload, the client sends a JSON payload to the API endpoint /api/file/upload-file:
{
	"category_id": "123",
	"name": "video.mp4",
	"thumbnailPath": "public/user123/thumbnail-abc123-video.mp4.png",
	"type": "video/mp4",
	"uploadFileNamePath": "abc123-video.mp4"
}
  • For non-video files, thumbnailPath is null.

2. Server-Side (API) Flow

a. Receiving the Request

  • The API receives a JSON payload (not form data).
  • It extracts all necessary fields from request.body.

b. Video Thumbnail Handling

  • If thumbnailPath is provided (i.e., for videos):
    1. The API copies the thumbnail from the location to its final location:
      public/{userId}/thumbnail-{uploadFileNamePath}.png
    2. The thumbnail is deleted from storage.
    3. The public URL for the thumbnail is generated and used as the ogImage.
    4. (Optional) Blurhash and metadata are generated for the thumbnail.

c. Database Insertion

  • The API inserts a new record into the main table with:
    • File URL (from storage)
    • Title, type, category, user ID
    • Thumbnail URL (if video)
    • Metadata (including blurhash, etc.)

d. Post-Processing

  • For non-video files, the API may trigger additional processing (e.g., image captioning, OCR, etc.)
  • Embeddings are created for search.

e. Remaining File Data Processing

  • For non-video files, after the initial upload, a separate API call is made to /api/file/upload-file-remaining-data.
  • This API processes the file to extract additional metadata:
    • OCR: Extracts text from images using Google's Generative AI
    • Image Captioning: Generates descriptions for images
    • Blurhash: Creates blur hash for image previews
  • The metadata is then updated in the database.

3. Storage Structure

  • Main files: public/{userId}/{uploadFileNamePath}
  • Video thumbnails : public/{userId}/thumbnail-{uploadFileNamePath}.png
  • Video thumbnails (final): public/{userId}/thumbnail-{uploadFileNamePath}.png

4. API Request Example

Endpoint: POST /api/file/upload-file

Headers:

Content-Type: application/json

Body:

{
	"category_id": "123",
	"name": "video.mp4",
	"thumbnailPath": "public/user123/thumbnail-abc123-video.mp4.png",
	"type": "video/mp4",
	"uploadFileNamePath": "abc123-video.mp4"
}

5. React Query Implementation

Optimistic Updates

The useFileUploadOptimisticMutation hook provides a smooth user experience by:

  1. Immediate UI Update: Shows the file in the list before the upload completes
  2. Background Processing: Handles file upload and API calls in the background
  3. Error Recovery: Rolls back the UI if the upload fails
  4. Cache Management: Invalidates and refetches data after successful upload

Key React Query Features Used

  • onMutate: Handles optimistic updates and file uploads
  • onError: Rolls back optimistic updates on failure
  • onSettled: Refreshes data after completion
  • onSuccess: Shows success messages and handles type-specific notifications

File Upload Process in React Query

const fileUploadOptimisticMutation = useMutation(uploadFile, {
	onMutate: async (data) => {
		// 1. Cancel outgoing queries
		// 2. Snapshot previous data
		// 3. Optimistically update UI
		// 4. Upload file to Supabase Storage
		// 5. Return context for rollback
	},
	onError: (context) => {
		// Rollback optimistic update
	},
	onSettled: () => {
		// Invalidate and refetch data
	},
	onSuccess: (response, data) => {
		// Show success messages
	},
});

6. Flow Diagram

graph TD
  A[User selects file(s)] --> B[Optimistic UI update]
  B --> C{Is video?}
  C -- No --> D[Upload file to Supabase Storage]
  C -- Yes --> E[Generate video thumbnail]
  E --> F[Upload thumbnail to location]
  F --> G[Upload video file to Supabase Storage]
  D & G --> H[Send JSON metadata to API]
  H --> I{Is video?}
  I -- No --> J[Insert file record in DB]
  I -- Yes --> K[Move thumbnail to final location]
  K --> L[Generate thumbnail metadata]
  L --> M[Insert file + thumbnail record in DB]
  J & M --> N[Trigger post-processing]
  N --> O{Is non-video?}
  O -- Yes --> P[Call remaining data API]
  P --> Q[Extract OCR, captions, blurhash]
  Q --> R[Update metadata in DB]
  O -- No --> S[Complete]
  R --> S
Loading

7. API Endpoints

Main Upload API

Endpoint: POST /api/file/upload-file Purpose: Handles initial file upload and database insertion Content-Type: application/json

Remaining Data API

Endpoint: POST /api/file/upload-file-remaining-data Purpose: Processes non-video files for additional metadata Content-Type: application/json Body:

{
	"id": 123,
	"publicUrl": "https://example.com/file.jpg"
}

8. Key Points

  • No form data: All API requests use JSON.
  • No file uploads via API: All files (including thumbnails) are uploaded directly to Supabase Storage from the client.
  • Efficient for large files: Bypasses Vercel's serverless size limits.
  • Optimistic updates: React Query provides immediate UI feedback.
  • Clean, modern, and maintainable.

9. References


For any questions or improvements, please refer to the code in src/async/uploads/file-upload.ts, src/pages/api/file/upload-file.ts, and related files.