laravel-files/docs/uploading.md

199 lines
3.9 KiB
Markdown
Raw Permalink Normal View History

2026-04-14 08:20:55 +00:00
# Uploading Files
The package provides a complete upload API with support for single-file uploads and chunked uploads for large files.
## Single File Upload
### Endpoint
```
POST /api/files/upload
```
**Middleware:** `api`, `auth:sanctum` (configurable)
### Request
Send a multipart form upload with a `file` field:
```bash
curl -X POST https://app.test/api/files/upload \
-H "Authorization: Bearer $TOKEN" \
-F "file=@photo.jpg"
```
### Validation
- **Max size:** 50 MB (configurable via `files.upload.max_size`)
- **Allowed MIME types:** all by default; restrict via `files.upload.allowed_mimes`
```php
// config/files.php
'upload' => [
'max_size' => 50 * 1024, // KB
'allowed_mimes' => ['jpg', 'png', 'pdf', 'docx'], // empty = allow all
],
```
### Response (201)
```json
{
"id": "9c3a...",
"name": "photo",
"type": "image/jpeg",
"extension": "jpg",
"size": 245760,
"size_human": "240 KB",
"url": "https://app.test/warehouse/9c3a..."
}
```
---
## Chunked Upload
For large files that exceed browser or server limits, use the chunked upload flow.
### Step 1: Initialize
```
POST /api/files/chunk/init
```
**Body (JSON):**
```json
{
"filename": "video.mp4",
"filesize": 104857600,
"total_chunks": 100,
"mime_type": "video/mp4",
"extension": "mp4"
}
```
**Response (201):**
```json
{
"upload_id": "9c3a...",
"file_id": "9c3a...",
"total_chunks": 100
}
```
### Step 2: Upload Chunks
```
POST /api/files/chunk/upload
```
Send each chunk as a multipart upload or raw body:
```bash
curl -X POST https://app.test/api/files/chunk/upload \
-H "Authorization: Bearer $TOKEN" \
-F "upload_id=9c3a..." \
-F "chunk_index=0" \
-F "chunk=@chunk_0.bin"
```
**Response:**
```json
{
"upload_id": "9c3a...",
"chunk_index": 0,
"received": 1,
"total_chunks": 100,
"complete": false
}
```
When the last chunk is received (`complete: true`), all chunks are automatically assembled into the final file.
### Step 3: Done
No finalization call needed. The file is ready to use once `complete` is `true`. The temporary chunk files are cleaned up automatically.
---
## Upload Sessions
Chunk upload sessions are stored in the application cache and expire after **24 hours**. If a session expires before all chunks are received, the upload must be restarted.
---
## Real-Time Progress
If [laravel-websockets](https://github.com/blax-software/laravel-websockets) is installed, a `ChunkUploadProgress` event is broadcast after each chunk:
```php
// Event payload
[
'uploadId' => '9c3a...',
'chunkIndex' => 42,
'totalChunks' => 100,
'complete' => false,
]
```
Listen on the client side to show upload progress bars.
---
## Upload via the HasFiles Trait
When working with models that use `HasFiles`, you can upload and attach in a single call:
```php
// From a form upload
$file = $product->uploadFile(
$request->file('photo'),
as: FileLinkType::Gallery,
);
// From raw content
$file = $product->uploadFileFromContents(
contents: $csvData,
name: 'export',
extension: 'csv',
as: FileLinkType::Document,
);
// From a URL
$file = $product->uploadFileFromUrl(
url: 'https://cdn.example.com/image.jpg',
as: FileLinkType::Banner,
replace: true,
);
```
See [Attaching Files](attaching-files.md#upload-helpers) for full parameter details.
---
## Route Configuration
Customize upload route prefix and middleware in `config/files.php`:
```php
'upload' => [
'route_prefix' => 'api/files',
'middleware' => ['api', 'auth:sanctum'],
],
```
**Routes registered:**
| Method | URI | Name |
|--------|-------------------------|----------------------|
| `POST` | `{prefix}/upload` | `files.upload` |
| `POST` | `{prefix}/chunk/init` | `files.chunk.init` |
| `POST` | `{prefix}/chunk/upload` | `files.chunk.upload` |
---
Next: [Serving Files](serving-files.md)