求助:Laravel 5.5结合Pion分片上传与Vue组件的完整示例
嘿,刚好我之前在Laravel 5.5上折腾过Pion分片上传结合Simple Uploader Vue组件,给你一套完整的可运行方案,亲测没问题!
一、前端Vue组件实现(Simple Uploader)
首先得安装依赖:
npm install simple-uploader-vue --save
然后创建一个ChunkUploader.vue组件,包含拖拽、进度显示、暂停/继续功能:
<template> <div class="chunk-uploader"> <div class="upload-area" @click="triggerFileInput" @drop="handleDrop" @dragover="handleDragOver"> <p>点击或拖拽文件到此处上传</p> <input type="file" ref="fileInput" multiple @change="handleFileSelect" style="display: none;"> </div> <div class="upload-list" v-for="file in uploader.files" :key="file.id"> <div class="file-info"> <span>{{ file.name }}</span> <span>{{ (file.size / 1024 / 1024).toFixed(2) }}MB</span> </div> <div class="progress-bar"> <div class="progress" :style="{ width: file.progress + '%' }"></div> </div> <div class="actions"> <button @click="file.pause()" v-if="file.status === 'uploading'">暂停</button> <button @click="file.resume()" v-if="file.status === 'paused'">继续</button> <button @click="file.cancel()">取消</button> </div> </div> </div> </template> <script> import SimpleUploader from 'simple-uploader-vue' export default { components: { SimpleUploader }, data() { return { uploader: null } }, mounted() { this.initUploader() }, methods: { initUploader() { this.uploader = new SimpleUploader({ target: '/api/upload/chunk', // 替换成你的后端分片上传接口地址 chunkSize: 5 * 1024 * 1024, // 5MB分片,可根据服务器配置调整 chunkRetry: 3, // 分片上传失败自动重试次数 simultaneousUploads: 2, // 同时上传的分片数量 // 关键:适配Pion的参数命名规则 query: (file, chunk) => { return { chunk_index: chunk.index + 1, // Simple Uploader的索引从0开始,Pion默认从1开始 chunk_size: chunk.size, total_size: file.size, filename: file.name, total_chunks: file.chunks.length, file_identifier: file.uniqueIdentifier // 用于断点续传的文件唯一标识 } }, // 上传成功回调 success: (file, response) => { console.log('文件上传完成:', response) alert(`${file.name} 上传成功!`) }, // 上传失败回调 error: (file, message) => { console.error('上传失败:', message) alert(`${file.name} 上传失败,请重试`) } }) }, triggerFileInput() { this.$refs.fileInput.click() }, handleFileSelect(e) { const files = Array.from(e.target.files) files.forEach(file => this.uploader.addFile(file)) }, handleDrop(e) { e.preventDefault() const files = Array.from(e.dataTransfer.files) files.forEach(file => this.uploader.addFile(file)) }, handleDragOver(e) { e.preventDefault() e.currentTarget.classList.add('dragover') setTimeout(() => { e.currentTarget.classList.remove('dragover') }, 100) } } } </script> <style scoped> .upload-area { border: 2px dashed #ccc; padding: 30px; text-align: center; cursor: pointer; margin-bottom: 20px; border-radius: 8px; } .upload-area.dragover { border-color: #2196F3; background-color: rgba(33, 150, 243, 0.1); } .upload-list { margin-bottom: 12px; padding: 12px; border: 1px solid #eee; border-radius: 8px; } .file-info { display: flex; justify-content: space-between; margin-bottom: 8px; font-size: 14px; } .progress-bar { height: 10px; background-color: #f5f5f5; border-radius: 5px; overflow: hidden; margin-bottom: 8px; } .progress { height: 100%; background-color: #2196F3; transition: width 0.3s ease; } .actions button { margin-right: 8px; padding: 4px 10px; border: none; border-radius: 4px; cursor: pointer; background-color: #2196F3; color: white; font-size: 14px; } .actions button:hover { opacity: 0.8; } </style>
二、后端Laravel适配(Pion Chunk Upload)
如果你已经安装了Pion,直接调整控制器和路由即可:
1. 路由配置(routes/api.php)
Route::post('/upload/chunk', 'ChunkUploadController@upload');
2. 控制器实现(app/Http/Controllers/ChunkUploadController.php)
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Pion\Laravel\ChunkUpload\Receiver\FileReceiver; use Pion\Laravel\ChunkUpload\Handler\HandlerFactory; use Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException; class ChunkUploadController extends Controller { public function upload(Request $request) { // 初始化文件接收器,对应前端上传的文件字段名是`file` $receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request)); // 检查是否有上传文件 if (!$receiver->isUploaded()) { throw new UploadMissingFileException(); } // 接收分片 $save = $receiver->receive(); // 判断是否所有分片都上传完成 if ($save->isFinished()) { // 获取合并后的完整文件 $file = $save->getFile(); // 生成唯一文件名,避免重复 $fileName = uniqid() . '.' . $file->getClientOriginalExtension(); // 移动文件到公共存储目录(记得先执行`php artisan storage:link`创建软链接) $file->move(storage_path('app/public/uploads'), $fileName); // 返回上传成功的响应,给前端提示 return response()->json([ 'status' => 'success', 'file_name' => $fileName, 'file_url' => asset('storage/uploads/' . $fileName) ]); } // 返回当前上传进度 $handler = $save->handler(); return response()->json([ 'done' => $handler->getPercentageDone(), 'status' => 'uploading' ]); } }
三、在页面中使用组件
比如在你的Vue页面里引入并使用:
<template> <div class="upload-page"> <h2>大文件分片上传测试</h2> <ChunkUploader /> </div> </template> <script> import ChunkUploader from './components/ChunkUploader.vue' export default { components: { ChunkUploader } } </script> <style scoped> .upload-page { max-width: 800px; margin: 40px auto; padding: 0 20px; } </style>
四、关键注意事项
- 服务器配置:修改
php.ini中的参数,确保支持大文件:upload_max_filesize = 100M post_max_size = 100M max_execution_time = 300 max_input_time = 300 - 存储链接:执行
php artisan storage:link,让前端可以访问storage/app/public目录下的文件。 - 断点续传:Simple Uploader会自动处理断点续传,因为它用
uniqueIdentifier标识文件,Pion也支持自动识别未完成的分片。 - 参数对应:一定要确保前端传递的参数名和Pion的要求一致,比如
chunk_index(Pion默认用这个,而Simple Uploader默认是chunkNumber),我已经在组件的query方法里做了转换。
内容的提问来源于stack exchange,提问作者Levente Berky
相关产品推荐
相关产品推荐

