mohamedgaldi/vilt-filepond
Composer 安装命令:
composer require mohamedgaldi/vilt-filepond
包简介
A Laravel package for handling file uploads with FilePond in VILT stack
README 文档
README
A comprehensive Laravel package for handling file uploads using FilePond in VILT (Vue, Inertia, Laravel, Tailwind) stack applications.
Features
- 🚀 Easy Integration - Seamless FilePond integration with Laravel
- 📊 Polymorphic Relations - Works with any Eloquent model
- 💾 Chunked Uploads - Support for large file uploads via chunking
- 🔄 Smart Management - Temporary file handling with automatic cleanup
- 📁 Flexible Uploads - Support for single and multiple file uploads
- 🏷️ Collections - Organize files using collections (images, documents, etc.)
- 🌐 Multi-language - Supports multiple locales (Arabic, French, Spanish, English)
- 🌗 Light/Dark Mode - Customizable theme with light and dark mode support
- 🔒 Security First - Built-in validation and security features
Requirements
- Laravel 11.0 or higher
- VILT stack (Vue.js, Inertia.js, Laravel, Tailwind CSS)
- PHP 8.1 or higher
Installation
1. Install the Package
composer require mohamedgaldi/vilt-filepond
2. Install Frontend Dependencies
npm install filepond vue-filepond filepond-plugin-file-validate-type filepond-plugin-file-validate-size filepond-plugin-image-preview
3. Publish Package Assets
# Publish everything at once php artisan vendor:publish --tag=vilt-filepond # Or publish individual assets php artisan vendor:publish --tag=vilt-filepond-config php artisan vendor:publish --tag=vilt-filepond-migrations php artisan vendor:publish --tag=vilt-filepond-vue
4. Import FilePond Styles
Add the following imports to your app.css file before your Tailwind directives:
@import "filepond/dist/filepond.min.css"; @import "filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css"; @tailwind base; @tailwind components; @tailwind utilities;
⚠️ Important: The FilePond CSS imports must come before Tailwind directives to ensure proper styling.
5. Run Migrations
php artisan migrate
6. Configure Storage
Ensure your public disk is properly configured in config/filesystems.php and create the storage link:
php artisan storage:link
7. Environment Configuration
APP_URL Configuration
Ensure your APP_URL in .env matches your development server URL:
# ❌ Wrong - will cause image loading issues APP_URL=http://localhost # ✅ Correct - matches your actual server URL APP_URL=http://127.0.0.1:8000
8. Configure Inertia Middleware
Add the CSRF token and config values to your HandleInertiaRequests middleware:
// app/Http/Middleware/HandleInertiaRequests.php public function share(Request $request): array { return [ ...parent::share($request), 'user' => fn () => $request->user() ? $request->user()->only('name', 'email') : null, 'csrf_token' => csrf_token(), 'fileUploadConfig' => [ 'locale' => config('vilt-filepond.locale'), 'chunkSize' => config('vilt-filepond.chunk_size'), ], ]; }
Quick Start
1. Prepare Your Model
Add the HasFiles trait to any model that needs file uploads:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use MohamedGaldi\ViltFilepond\Traits\HasFiles; class Product extends Model { use HasFiles; protected $fillable = ['name', 'description']; }
2. Create a New Record with Files
<script setup> import { useForm } from "@inertiajs/vue3"; import FileUpload from "@/Components/ViltFilePond/FileUpload.vue"; import { ref } from "vue"; const form = useForm({ name: "", images: [], }); const fileUploadRef = ref(null); function handleSubmit() { form.post(route("products.store"), { onSuccess: () => { form.reset(); fileUploadRef.value?.resetFiles(); }, }); } </script> <template> Packed <form @submit.prevent="handleSubmit"> <div class="mb-4"> <label class="block text-sm font-medium text-gray-700">Name</label> <input v-model="form.name" type="text" class="mt-1 block w-full rounded-md border-gray-300" required /> </div> <div class="mb-4"> <label class="block text-sm font-medium text-gray-700">Images</label> <FileUpload ref="fileUploadRef" v-model="form.images" :allow-multiple="true" :max-files="5" collection="images" theme="light" width="40rem" /> </div> <button type="submit" :disabled="form.processing" class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 disabled:opacity-50" > {{ form.processing ? "Saving..." : "Create Product" }} </button> </form> </template>
3. Update Existing Records
<script setup> import { useForm } from "@inertiajs/vue3"; import { ref, watch } from "vue"; import FileUpload from "@/Components/ViltFilePond/FileUpload.vue"; const props = defineProps({ product: Object, }); // State management const tempFolders = ref([]); const removedFileIds = ref([]); const form = useForm({ name: props.product?.name || "", images_temp_folders: [], images_removed_files: [], }); // Sync temp folders with form watch( tempFolders, (newValue) => { form.images_temp_folders = [...newValue]; }, { deep: true } ); // Handle file removal function handleFileRemoved(data) { if (data.type === "existing" && data.fileId) { removedFileIds.value.push(data.fileId); form.images_removed_files = [...removedFileIds.value]; } } function handleSubmit() { form.put(route("products.update", props.product.id)); } </script> <template> <div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-4 text-2xl"> <form @submit.prevent="handleSubmit"> <div class="mb-4"> <label>Name</label> <input v-model="form.name" type="text" class="mt-1 block w-full rounded-md border-gray-300" /> </div> <div class="mb-4"> <label>Images</label> <FileUpload v-model="tempFolders" :initial-files="product?.files || []" :allow-multiple="true" :max-files="5" collection="images" theme="light" width="40rem" @file-removed="handleFileRemoved" /> </div> <button type="submit" :disabled="form.processing" class="bg-blue-500 text-white px-4 py-2 rounded" > {{ form.processing ? "Updating..." : "Update Product" }} </button> </form> </div> </template>
4. Handle Files in Controller
<?php namespace App\Http\Controllers; use App\Models\Product; use Illuminate\Http\Request; use MohamedGaldi\ViltFilepond\Services\FilePondService; class ProductController extends Controller { protected FilePondService $filePondService; public function __construct(FilePondService $filePondService) { $this->filePondService = $filePondService; } public function store(Request $request) { $request->validate([ 'name' => 'required|string|max:255', 'images' => 'array', 'images.*' => 'string', ]); $product = Product::create($request->only(['name'])); // Handle file uploads if ($request->has('images') && !empty($request->images)) { $this->filePondService->handleFileUploads( $product, $request->images, 'images' ); } return redirect() ->route('products.index') ->with('success', 'Product created successfully!'); } public function update(Request $request, Product $product) { $request->validate([ 'name' => 'required|string|max:255', 'images_temp_folders' => 'array', 'images_removed_files' => 'array', ]); $product->update($request->only(['name'])); // Handle file updates $this->filePondService->handleFileUpdates( $product, $request->input('images_temp_folders', []), $request->input('images_removed_files', []), 'images' ); return redirect() ->route('products.index') ->with('success', 'Product updated successfully!'); } }
Component Props
FileUpload Component
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue |
Array | [] |
Array of temporary folder names |
initialFiles |
Array | [] |
Array of existing files to display |
allowedFileTypes |
Array | Image types | Accepted MIME types |
allowMultiple |
Boolean | false |
Allow multiple file uploads |
maxFiles |
Number | 1 |
Maximum number of files |
maxFileSize |
String | "10MB" |
Maximum file size |
collection |
String | "default" |
File collection name |
disabled |
Boolean | false |
Disable the component |
required |
Boolean | false |
Mark as required field |
theme |
String | "light" |
Theme for the component (light or dark) |
width |
String | "auto" |
Custom width for the component (e.g., "40rem") |
Events
| Event | Payload | Description |
|---|---|---|
@file-added |
{ folder, file } |
Fired when a file is uploaded |
@file-removed |
{ fileId, type, file } |
Fired when a file is removed |
@error |
error |
Fired when an error occurs |
Configuration
Customize the package behavior in config/vilt-filepond.php:
<?php return [ // The disk where files will be stored permanently 'storage_disk' => 'public', // path where temporary files are stored before being moved to permanent location 'temp_path' => 'temp-files', // Base path where permanent files are stored 'files_path' => 'files', // Files larger than this size (in bytes) will be uploaded in chunks. 'chunk_size' => 10 * 1024 * 1024, // 10MB // Configure the FilePond locale. Set to null for English (default). // Supported locales: 'ar', 'fr', 'es', null (English) 'locale' => null, // Configuration for the package routes 'routes' => [ 'prefix' => 'filepond', 'middleware' => ['web'], ], ];
API Reference
HasFiles Trait Methods
| Method | Description |
|---|---|
files() |
Get all files relationship |
getFilesByCollection(string $collection) |
Get files by collection |
getFirstFile(string $collection = 'default') |
Get first file from collection |
hasFiles(string $collection = null) |
Check if model has files |
deleteFiles(string $collection = null) |
Delete files by collection |
FilePondService Methods
| Method | Description |
|---|---|
storeTempFile(UploadedFile $file, string $collection) |
Store temporary file |
moveTempFileToModel($model, string $folder, string $collection, int $order) |
Move temp file to model |
handleFileUploads($model, array $tempFolders, string $collection) |
Handle multiple uploads |
handleFileUpdates($model, array $tempFolders, array $removedFiles, string $collection) |
Handle file updates |
cleanupTempFiles() |
Clean up old temporary files |
Troubleshooting
Common Issues
- Images not loading: Check your
APP_URLin.envmatches your server URL - Styles not working: Ensure FilePond CSS is imported before Tailwind
- Upload failures: Verify CSRF token is shared via Inertia middleware
- Permission errors: Run
php artisan storage:linkand check file permissions
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This package is open-sourced software licensed under the MIT license.
Made with ❤️ for the VILT Stack community
mohamedgaldi/vilt-filepond 适用场景与选型建议
mohamedgaldi/vilt-filepond 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 891 次下载、GitHub Stars 达 12, 最近一次更新时间为 2025 年 06 月 27 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「upload」 「laravel」 「file upload」 「vue」 「filepond」 「vilt」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 mohamedgaldi/vilt-filepond 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 mohamedgaldi/vilt-filepond 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 mohamedgaldi/vilt-filepond 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
The file manager intended for using Laravel with CKEditor / TinyMCE / Colorbox
Laravel Media Popup to upload/view the files
PMVC Plugin for File information
Mapper for accessing resources in KWCMS
Text file manipulation
KCFinder web file manager
统计信息
- 总下载量: 891
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 12
- 点击次数: 30
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-06-27