wramirez83/fluxupload
Composer 安装命令:
composer require wramirez83/fluxupload
包简介
Laravel package for large file uploads using chunking with automatic resumption
README 文档
README
FluxUpload es un paquete Laravel que permite la subida de archivos grandes (superiores a 1GB) mediante chunking (división en partes) con capacidad de reanudación automática.
📋 Características
- ✅ Subida de archivos grandes (hasta 25GB)
- ✅ Chunking automático (división en partes)
- ✅ Reanudación automática de cargas interrumpidas
- ✅ Validación de integridad mediante hash (opcional)
- ✅ Soporte para múltiples discos de almacenamiento (Local, S3, MinIO, Azure Blob)
- ✅ API REST completa
- ✅ Cliente JavaScript incluido
- ✅ Eventos para integración
- ✅ Limpieza automática de sesiones expiradas
- ✅ Compatible con Laravel 11, 12 y 13
📦 Instalación
Requisitos
- PHP 8.1 o superior (compatible con PHP 8.4)
- Laravel 11, 12 o 13 (
illuminate/support^11.0, ^12.0 o ^13.0) - Laravel 13 exige PHP 8.3+ según el framework; en PHP 8.4 el paquete se ejecuta y prueba sin cambios adicionales
- Extensiones PHP:
fileinfo,mbstring,openssl,json
Instalación vía Composer
composer require wramirez83/fluxupload
Versión actual: 3.1.0
Publicar configuración y migraciones
php artisan vendor:publish --tag=fluxupload-config php artisan vendor:publish --tag=fluxupload-migrations
Ejecutar migraciones
php artisan migrate
Publicar assets JavaScript (opcional)
php artisan vendor:publish --tag=fluxupload-assets
⚙️ Configuración
El archivo de configuración se encuentra en config/fluxupload.php. Puedes configurar:
// Tamaño de chunk por defecto (2MB en v3.0.0) 'chunk_size' => env('FLUXUPLOAD_CHUNK_SIZE', 2097152), // Tamaño máximo de archivo (25GB en v3.0.0) 'max_file_size' => env('FLUXUPLOAD_MAX_FILE_SIZE', 26843545600), // Expiración de sesiones (24 horas) 'session_expiration_hours' => env('FLUXUPLOAD_SESSION_EXPIRATION', 24), // Disco de almacenamiento 'storage_disk' => env('FLUXUPLOAD_STORAGE_DISK', 'local'), // Ruta de almacenamiento 'storage_path' => env('FLUXUPLOAD_STORAGE_PATH', 'fluxupload'), // Extensiones permitidas (vacío = todas) 'allowed_extensions' => env('FLUXUPLOAD_ALLOWED_EXTENSIONS') ? explode(',', env('FLUXUPLOAD_ALLOWED_EXTENSIONS')) : [], // Validar hash 'validate_hash' => env('FLUXUPLOAD_VALIDATE_HASH', false), 'hash_algorithm' => env('FLUXUPLOAD_HASH_ALGORITHM', 'sha256'),
Variables de entorno
Puedes configurar el paquete mediante variables de entorno en tu archivo .env:
FLUXUPLOAD_CHUNK_SIZE=2097152 FLUXUPLOAD_MAX_FILE_SIZE=26843545600 FLUXUPLOAD_SESSION_EXPIRATION=24 FLUXUPLOAD_STORAGE_DISK=local FLUXUPLOAD_STORAGE_PATH=fluxupload FLUXUPLOAD_ALLOWED_EXTENSIONS=pdf,doc,docx,zip FLUXUPLOAD_VALIDATE_HASH=true FLUXUPLOAD_HASH_ALGORITHM=sha256 FLUXUPLOAD_ROUTE_PREFIX=fluxupload FLUXUPLOAD_MIDDLEWARE=api
🚀 Uso Básico
API REST
1. Inicializar sesión de subida
POST /fluxupload/init Content-Type: application/json { "filename": "documento.pdf", "total_size": 104857600, "chunk_size": 2097152, "mime_type": "application/pdf", "hash": "sha256_hash_here" // opcional }
Respuesta:
{
"success": true,
"session_id": "abc123...",
"total_chunks": 50,
"chunk_size": 2097152,
"uploaded_chunks": 0,
"missing_chunks": [0, 1, 2, ..., 19],
"progress": 0
}
2. Subir chunk
POST /fluxupload/chunk Content-Type: multipart/form-data session_id: abc123... chunk_index: 0 chunk: [archivo binario]
Respuesta:
{
"success": true,
"message": "Chunk uploaded successfully",
"session_id": "abc123...",
"chunk_index": 0,
"uploaded_chunks": 1,
"total_chunks": 50,
"progress": 5.0,
"status": "uploading"
}
3. Consultar estado
GET /fluxupload/status/{session_id}
Respuesta:
{
"success": true,
"session_id": "abc123...",
"filename": "documento.pdf",
"status": "uploading",
"uploaded_chunks": 25,
"total_chunks": 50,
"total_size": 104857600,
"progress": 50.0,
"missing_chunks": [25, 26, 27, ..., 49],
"storage_path": null,
"error_message": null,
"expires_at": "2024-01-01T12:00:00Z"
}
Cliente JavaScript
Uso básico
<script src="/vendor/fluxupload/fluxupload.js"></script> <script> const uploader = new FluxUpload({ baseUrl: '/fluxupload', chunkSize: 2 * 1024 * 1024, // 2MB (v3.0.0) parallelUploads: 3, onProgress: (progress) => { console.log(`Progress: ${progress.progress}%`); }, onComplete: (status) => { console.log('Upload completed!', status); }, onError: (error) => { console.error('Upload error:', error); } }); // Subir archivo const fileInput = document.getElementById('fileInput'); fileInput.addEventListener('change', async (e) => { const file = e.target.files[0]; try { await uploader.upload(file); } catch (error) { console.error('Upload failed:', error); } }); </script>
Reanudar subida
// Si tienes un session_id previo uploader.sessionId = 'previous-session-id'; await uploader.resume();
Pausar/Cancelar
// Pausar uploader.pause(); // Cancelar uploader.cancel();
Uso en PHP (Backend)
use Wramirez83\FluxUpload\Facades\FluxUpload; // Obtener servicios $uploadService = FluxUpload::getUploadService(); $sessionService = FluxUpload::getSessionService(); $chunkService = FluxUpload::getChunkService(); // Crear sesión manualmente $session = $sessionService->createSession([ 'original_filename' => 'archivo.pdf', 'total_size' => 104857600, 'total_chunks' => 50, 'chunk_size' => 2097152, ]); // Obtener chunks faltantes $missingChunks = $sessionService->getMissingChunks($session->session_id); // Ensamblar archivo manualmente $uploadService->assembleFile($session);
📡 Eventos
FluxUpload emite eventos que puedes escuchar:
FluxUploadCompleted
Se emite cuando una subida se completa exitosamente.
use Wramirez83\FluxUpload\Events\FluxUploadCompleted; use Illuminate\Support\Facades\Event; Event::listen(FluxUploadCompleted::class, function (FluxUploadCompleted $event) { $session = $event->session; // Procesar archivo completado // $session->storage_path contiene la ruta del archivo final // $session->storage_disk contiene el disco donde se guardó });
FluxUploadFailed
Se emite cuando una subida falla.
use Wramirez83\FluxUpload\Events\FluxUploadFailed; Event::listen(FluxUploadFailed::class, function (FluxUploadFailed $event) { $session = $event->session; $error = $event->errorMessage; // Manejar error logger()->error("Upload failed: {$error}", [ 'session_id' => $session->session_id, ]); });
FluxUploadChunkReceived
Se emite cada vez que se recibe un chunk (opcional).
use Wramirez83\FluxUpload\Events\FluxUploadChunkReceived; Event::listen(FluxUploadChunkReceived::class, function (FluxUploadChunkReceived $event) { $session = $event->session; $chunk = $event->chunk; // Procesar chunk recibido });
🧹 Limpieza de Sesiones
Comando Artisan
Para limpiar sesiones expiradas manualmente:
php artisan fluxupload:clean
Modo dry-run
Para ver qué se eliminaría sin eliminar realmente:
php artisan fluxupload:clean --dry-run
Programar limpieza automática
En Laravel 11 y posteriores suele definirse en routes/console.php. En versiones anteriores, en app/Console/Kernel.php:
use Illuminate\Support\Facades\Schedule; Schedule::command('fluxupload:clean') ->daily() ->at('02:00');
Si aún usas Kernel con el método schedule:
protected function schedule(Schedule $schedule) { $schedule->command('fluxupload:clean') ->daily() ->at('02:00'); }
🔒 Seguridad
Autenticación
Puedes proteger las rutas mediante middleware. En config/fluxupload.php:
'middleware' => ['api', 'auth:sanctum'],
O usando middleware personalizado:
'middleware' => ['api', 'throttle:60,1'],
Validación de extensiones
'allowed_extensions' => ['pdf', 'doc', 'docx', 'zip'],
Validación de hash
Para validar la integridad del archivo:
'validate_hash' => true, 'hash_algorithm' => 'sha256', // o 'md5'
🧪 Pruebas
Ejecutar todas las pruebas:
composer test
O con PHPUnit directamente:
./vendor/bin/phpunit
Estructura de pruebas
tests/Unit/- Pruebas unitarias de servicios y modelostests/Feature/- Pruebas de integración de la API
📚 Ejemplos
Ejemplo completo con JavaScript
<!DOCTYPE html> <html> <head> <title>FluxUpload Example</title> </head> <body> <input type="file" id="fileInput"> <button id="uploadBtn">Upload</button> <button id="pauseBtn">Pause</button> <button id="resumeBtn">Resume</button> <div id="progress"></div> <script src="/vendor/fluxupload/fluxupload.js"></script> <script> const uploader = new FluxUpload({ baseUrl: '/fluxupload', chunkSize: 2 * 1024 * 1024, // 2MB (v3.0.0) parallelUploads: 3, onProgress: (progress) => { document.getElementById('progress').textContent = `Progress: ${progress.progress}% (${progress.uploaded}/${progress.total})`; }, onComplete: (status) => { alert('Upload completed!'); console.log('File saved at:', status.storage_path); }, onError: (error) => { alert('Upload failed: ' + error.message); } }); document.getElementById('uploadBtn').addEventListener('click', async () => { const fileInput = document.getElementById('fileInput'); if (fileInput.files.length > 0) { try { await uploader.upload(fileInput.files[0]); } catch (error) { console.error(error); } } }); document.getElementById('pauseBtn').addEventListener('click', () => { uploader.pause(); }); document.getElementById('resumeBtn').addEventListener('click', async () => { try { await uploader.resume(); } catch (error) { console.error(error); } }); </script> </body> </html>
Ejemplo con React
import { useState } from 'react'; import FluxUpload from './fluxupload'; function FileUploader() { const [progress, setProgress] = useState(0); const [uploader] = useState(() => new FluxUpload({ baseUrl: '/fluxupload', onProgress: (p) => setProgress(p.progress), onComplete: (status) => { console.log('Completed:', status); setProgress(100); }, onError: (error) => { console.error('Error:', error); } })); const handleFileChange = async (e) => { const file = e.target.files[0]; if (file) { await uploader.upload(file); } }; return ( <div> <input type="file" onChange={handleFileChange} /> <div>Progress: {progress}%</div> </div> ); }
🐛 Solución de Problemas
Error: "Session not found"
- Verifica que el
session_idsea correcto - Verifica que la sesión no haya expirado
- Revisa los logs de Laravel
Error: "Chunk size validation failed"
- Verifica que el tamaño del chunk coincida con el configurado
- El último chunk puede ser más pequeño que el tamaño configurado
Archivo no se ensambla correctamente
- Verifica que todos los chunks se hayan subido
- Revisa los permisos de escritura en el directorio de chunks
- Verifica el espacio en disco disponible
📝 Changelog
Ver CHANGELOG.md para más detalles.
🤝 Contribuir
Las contribuciones son bienvenidas. Por favor:
- Fork el proyecto
- Crea una rama para tu feature (
git checkout -b feature/AmazingFeature) - Commit tus cambios (
git commit -m 'Add some AmazingFeature') - Push a la rama (
git push origin feature/AmazingFeature) - Abre un Pull Request
📄 Licencia
Este paquete es de código abierto bajo la licencia MIT.
👥 Autores
- Medusa - Desarrollo inicial
🙏 Agradecimientos
- Laravel Framework
- Comunidad de desarrolladores PHP
¿Necesitas ayuda? Abre un issue en GitHub o contacta al equipo de desarrollo.
wramirez83/fluxupload 适用场景与选型建议
wramirez83/fluxupload 是一款 基于 HTML 开发的 Composer 扩展包,目前已累计 27 次下载、GitHub Stars 达 1, 最近一次更新时间为 2025 年 11 月 16 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「laravel」 「chunking」 「file-upload」 「large-files」 「resumable-upload」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 wramirez83/fluxupload 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 wramirez83/fluxupload 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 wramirez83/fluxupload 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
FineUploader bundle for Contao Open Source CMS
Integrates the rekalogika/file library into the Symfony framework.
Upload files using Symfony Form, FilePond, and the rekalogika/file framework
A powerful chunked file upload field for Filament using Uppy.js with S3, remote sources (Google Drive, OneDrive, Dropbox), webcam, screen capture, audio recording, image editing and more.
Symfony bundle for automatic file upload handling on Doctrine ORM entities with S3, CDN, and multiple storage support
A framework-agnostic PHP library for chunking text and files using pluggable strategies and post-processors.
统计信息
- 总下载量: 27
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 2
- 点击次数: 21
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-11-16