File Uploads
Relevant source files
The following files were used as context for generating this wiki page:The File Uploads system provides a robust mechanism for users to attach files to "Request" records within the application. It integrates with the device's native capabilities (camera, gallery, file system) and utilizes Supabase Storage for secure cloud-based file storage. The system is designed to handle various file types, enforce size and quantity limits, and associate the uploaded files with their corresponding requests.
This feature is primarily implemented through the FileUploadComponent, which is integrated into the "New Request" form. The component handles the user interface, while the fileUpload.ts utility manages the interaction with Supabase Storage. Backend configuration, including bucket creation and security policies, is managed via Node.js scripts.
Sources: RESUMEN_FINAL.md, app/(tabs)/requests.tsx, components/FileUploadComponent.tsx, utils/fileUpload.ts
System Architecture
The file upload process involves a frontend component, a utility module for backend communication, and Supabase Storage for persistence. The flow begins with the user interacting with the UI, which triggers native device pickers. Selected files are then processed by the upload utility, sent to Supabase, and their public URLs are stored in the requests database table.
This diagram illustrates the high-level architecture of the file upload system.
Backend Configuration (Supabase)
The backend relies on Supabase Storage, configured via dedicated scripts. This includes creating a specific bucket and applying Row Level Security (RLS) policies to control access.
Storage Bucket
A single public bucket named request-files is used to store all attachments.
| Property | Value | Source |
|---|---|---|
| Bucket Name | request-files | [create-storage-bucket.js:10](https://github.com/softvibeslab/elmecV2-Demo/blob/HEAD/create-storage-bucket.js#L10) |
| Access | Public | [create-storage-bucket.js:14](https://github.com/softvibeslab/elmecV2-Demo/blob/HEAD/create-storage-bucket.js#L14) |
| File Size Limit | 5MB | [RESUMEN_FINAL.md](https://github.com/softvibeslab/elmecV2-Demo/blob/HEAD/RESUMEN_FINAL.md) |
| Allowed MIME Types | image/*, application/pdf, text/*, etc. | [RESUMEN_FINAL.md](https://github.com/softvibeslab/elmecV2-Demo/blob/HEAD/RESUMEN_FINAL.md), [REPORTE_PRUEBAS_CRUD.md](https://github.com/softvibeslab/elmecV2-Demo/blob/HEAD/REPORTE_PRUEBAS_CRUD.md) |
The creation of this bucket is automated by the create-storage-bucket.js script.
Sources: create-storage-bucket.js, RESUMEN_FINAL.md
Security Policies (RLS)
Four Row Level Security (RLS) policies are applied to the storage.objects table to secure the request-files bucket. These policies ensure that while files are publicly readable, only authenticated users can manage their own content.
| Policy | Action | Target Role | Description |
|---|---|---|---|
| Public read access | SELECT | anon, authenticated | Anyone can read/download files from the request-files bucket. |
| Authenticated upload | INSERT | authenticated | Only authenticated users can upload files, associating them with their uid. |
| Owner can update | UPDATE | authenticated | Users can only update files they own. |
| Owner can delete | DELETE | authenticated | Users can only delete files they own. |
These policies are defined and can be applied using the setup-storage-policies.js script. The core logic relies on matching the user's authenticated uid with the owner_id of the storage object.
-- 2. Authenticated users can upload (INSERT)
-- Source: [RESUMEN_FINAL.md](https://github.com/softvibeslab/elmecV2-Demo/blob/HEAD/RESUMEN_FINAL.md)
(bucket_id = 'request-files' AND auth.uid()::text = owner_id)
-- 4. Users can delete own files (DELETE)
-- Source: [RESUMEN_FINAL.md](https://github.com/softvibeslab/elmecV2-Demo/blob/HEAD/RESUMEN_FINAL.md)
(bucket_id = 'request-files' AND auth.uid()::text = owner_id)
Sources: RESUMEN_FINAL.md, setup-storage-policies.js
This diagram shows the access control flow based on the RLS policies.
Sources: RESUMEN_FINAL.md, setup-storage-policies.js
Frontend Implementation
The frontend consists of the UI component for user interaction and a utility module that contains the core upload logic.
UI: FileUploadComponent.tsx
This component renders the user interface for adding files and is responsible for invoking the appropriate device API (expo-image-picker or expo-document-picker).
Key Features:
- Three Action Buttons:
📄 Archivo: Opens the device's document picker.🖼️ Galería: Opens the device's image gallery.📷 Cámara: Opens the device's camera (native platforms only).
- File List: Displays a list of selected files with their name, size, and a button to remove them before uploading.
- Validation: Enforces limits on the number of files (max 3) and total file size.
The necessary permissions for these actions are configured in app.json.
"plugins": [
//...
[
"expo-image-picker",
{
"photosPermission": "La app necesita acceso a tu galería para adjuntar imágenes.",
"cameraPermission": "La app necesita acceso a tu cámara para tomar fotos."
}
]
]
Sources: app.json, components/FileUploadComponent.tsx, RESUMEN_FINAL.md
Logic: utils/fileUpload.ts
This utility module abstracts the file upload process. Its primary export is uploadMultipleFiles, which orchestrates the upload of an array of file assets to Supabase Storage.
Key Functions & Logic:
uploadFileToStorage(file, bucket, folder):- Takes a single file asset.
- Reads the file into a Base64 string using
expo-file-system. - Generates a unique file path using a timestamp and random string to prevent collisions.
- Uploads the file to Supabase Storage using
supabase.storage.from(bucket).upload(). - Retrieves and returns the public URL of the uploaded file.
uploadMultipleFiles(...):- Iterates over an array of file assets.
- Calls
uploadFileToStoragefor each file. - Collects the results and returns an array of objects containing the public URL and other metadata.
- Validations:
- Checks if the file size exceeds a 5MB limit before attempting to upload.
Sources: utils/fileUpload.ts, TEST_REPORT.md
Data Flow Sequence
The following sequence diagram details the entire process from user interaction to the file URL being ready for submission.
Testing
The file upload system is validated through automated scripts that test the core CRUD (Create, Read, Update, Delete) operations against the Supabase Storage bucket.
Key Validated Operations:
- CREATE: Uploading text and CSV files.
- READ: Listing files, generating public URLs, and downloading content to verify integrity.
- DELETE: Removing individual and multiple files.
The test report indicates that all critical operations for the app's functionality (uploading images/PDFs, reading, and deleting) are 100% functional. Some non-critical tests, like uploading JSON files or immediate verification after an update, showed issues related to MIME type restrictions and caching, but these do not impact the primary use case.
Sources: REPORTE_PRUEBAS_CRUD.md, RESUMEN_FINAL.md
Conclusion
The file upload system is a complete and well-tested feature. It provides a secure and user-friendly way to attach files to requests by leveraging Expo's native APIs and Supabase's scalable storage solution. The backend is properly secured with RLS policies, and the frontend provides a clear interface with necessary client-side validations. The system is considered production-ready for its intended purpose.
Sources: RESUMEN_FINAL.md, REPORTE_FINAL_VALIDACION.md