You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:10:02