Spaces:
Sleeping
Sleeping
File size: 6,593 Bytes
05c5ed5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | # File Storage Setup
> **Note**: This documentation was written by Claude 3.5 Sonnet.
This project supports **cloud-based file storage** for handling file uploads and downloads.
## Overview
Files are stored with **public access** by default, making them accessible via URL. This is useful for sharing uploaded content, displaying images, and integrating with external services.
## Storage Drivers
The project supports two storage backends:
- **Vercel Blob** - Default for all deployments (recommended)
- **S3** - Planned for AWS/S3-compatible storage
**Vercel Blob** is the default storage driver and works seamlessly in both local development and production environments.
## Configuration
### Environment Variables
```ini
# Storage driver selection (defaults to vercel-blob)
FILE_STORAGE_TYPE=vercel-blob # or s3 (coming soon)
# Optional: Subdirectory prefix for organizing files
FILE_STORAGE_PREFIX=uploads
# === Vercel Blob (FILE_STORAGE_TYPE=vercel-blob) ===
BLOB_READ_WRITE_TOKEN=<auto on Vercel>
VERCEL_BLOB_CALLBACK_URL= # Optional: For local webhook testing with ngrok
# === S3 (FILE_STORAGE_TYPE=s3, not yet implemented) ===
# FILE_STORAGE_S3_BUCKET=
# FILE_STORAGE_S3_REGION=
# AWS_ACCESS_KEY_ID=
# AWS_SECRET_ACCESS_KEY=
```
### Quick Start with Vercel Blob
Vercel Blob works in both local development and production environments:
1. Go to your Vercel project β **Storage** tab
2. Click **Connect Database** β **Blob** β **Continue**
3. Name it (e.g., "Files") and click **Create**
4. Pull environment variables locally:
```bash
vercel env pull
```
That's it! File uploads will now work seamlessly in both development and production.
## Client Upload
The `useFileUpload` hook **automatically selects the optimal upload method** based on your storage backend:
- **Vercel Blob**: Direct browser β CDN upload (fastest, default)
- **S3**: Presigned URL upload (when implemented)
```tsx
"use client";
import { useFileUpload } from "hooks/use-presigned-upload";
function FileUploadComponent() {
const { upload, isUploading } = useFileUpload();
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
const result = await upload(file);
if (!result) return; // Upload failed (error shown via toast)
// File uploaded successfully
console.log("Public URL:", result.url);
console.log("Pathname (key):", result.pathname);
};
return (
<input type="file" onChange={handleFileChange} disabled={isUploading} />
);
}
```
### Upload Flow
#### Vercel Blob (Direct Upload)
```mermaid
sequenceDiagram
participant Browser
participant UploadURL as /api/storage/upload-url
participant Vercel as Vercel Blob CDN
Browser->>UploadURL: POST (request client token)
Note over Browser,UploadURL: User authenticated
UploadURL->>Vercel: Generate client token
Vercel-->>UploadURL: Return token
UploadURL-->>Browser: Return token + URL
Browser->>Vercel: PUT file (with token)
Vercel-->>Browser: Upload complete
Vercel->>UploadURL: Webhook: upload completed
Note over UploadURL: Optional: Save to DB
```
### Features
- β
**Cloud-Based Storage**: Vercel Blob provides globally distributed CDN
- β
**Works Everywhere**: Same storage in development and production
- β
**Direct Client Upload**: Browser uploads directly to CDN (fastest)
- β
**Public Access**: All files get public URLs
- β
**Authentication**: Users must be logged in to upload
- β
**Collision Prevention**: UUID-based file naming
- β
**Type Safety**: Full TypeScript support with unified interface
## Server-Side Upload
For server-side uploads (e.g., programmatically generated files):
```ts
import { serverFileStorage } from "lib/file-storage";
const result = await serverFileStorage.upload(buffer, {
filename: "generated-image.png",
contentType: "image/png",
});
console.log("Public URL:", result.sourceUrl);
```
## Upload Completion Webhook
The `/api/storage/upload-url` endpoint handles the `onUploadCompleted` webhook from Vercel Blob. You can add custom logic here:
```ts
// src/app/api/storage/upload-url/route.ts
onUploadCompleted: async ({ blob, tokenPayload }) => {
const { userId } = JSON.parse(tokenPayload);
// Save to database
await db.files.create({
url: blob.url,
pathname: blob.pathname,
userId,
size: blob.size,
contentType: blob.contentType,
});
// Send notification
// await sendNotification(userId, "File uploaded!");
};
```
## Advanced
### Local Development with Vercel Blob Webhooks
To test Vercel Blob's `onUploadCompleted` webhook locally, use [ngrok](https://ngrok.com/):
```bash
# Terminal 1: Start your app
pnpm dev
# Terminal 2: Start ngrok
ngrok http 3000
# Add to .env.local
VERCEL_BLOB_CALLBACK_URL=https://abc123.ngrok-free.app
```
Without ngrok, uploads will work but `onUploadCompleted` won't be called locally.
### Custom Storage Backend
To implement a custom storage driver (e.g., Cloudflare R2, MinIO, S3):
1. Create a new file in `src/lib/file-storage/` (e.g., `r2-file-storage.ts`)
2. Implement the `FileStorage` interface from `file-storage.interface.ts`
3. Add your driver to `index.ts`
4. Update `FILE_STORAGE_TYPE` environment variable
The `FileStorage` interface provides:
- `upload()` - Server-side file upload
- `createUploadUrl()` - Generate presigned URL for client uploads (optional)
- `download()`, `delete()`, `exists()`, `getMetadata()`, `getSourceUrl()`
### Storage Comparison
| Feature | Vercel Blob | S3 (Planned) |
| -------------------- | ------------------- | ------------------ |
| Direct Client Upload | β
Yes | β
Yes (presigned) |
| CDN | β
Global | Configurable |
| Cost | Pay-as-you-go | Pay-as-you-go |
| Best For | All deployments | AWS ecosystem |
| Setup Complexity | Minimal | Moderate |
| Local Development | β
Works with token | β
Works |
## Why Not Local Filesystem?
Local filesystem storage is **not supported** because:
1. **AI APIs can't access localhost**: When AI APIs receive `http://localhost:3000/file.png`, they cannot fetch the file
2. **Serverless incompatibility**: Platforms like Vercel don't support persistent filesystem
3. **No CDN**: Files aren't globally distributed
**Solution**: Vercel Blob provides a free tier and works seamlessly in both local development and production. Simply run `vercel env pull` to get your token locally.
|