Laravel集成FilePond分片上传:如何获取PATCH请求内容?
FilePond + Laravel 分片上传:获取PATCH请求内容的解决方案
问题描述
有没有开发者尝试过使用FilePond与Laravel实现文件分片上传?我正尝试完成该功能,但不知道如何获取PATCH请求的内容。上传启动后会收到多个PATCH请求,在Firefox开发者工具的网络面板中可以看到这些请求因offset不同而存在差异。
我的Blade视图代码
<form action="{{ route('upload.store') }}" enctype="multipart/form-data" method="post"> @csrf <input class="" id="imageUploadFilePond" name="file" type="file"> <button class="btn btn-primary" type="submit">Submit</button> </form> @push('scripts') <script src="https://unpkg.com/filepond@^4/dist/filepond.js"></script> <script> const inputElement = document.querySelector('#imageUploadFilePond'); const pond = FilePond.create(inputElement, { server: { url: '/upload', patch: "/", headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }, }, chunkUploads: true, chunkSize: 1048576, chunkForce: true, }); </script> @endpush
我的UploadController.php代码
public function store(Request $request) { if ($request->file === '{}') { return uniqid(); } return ''; } public function update(Request $request, $id) { $uploadOffset = $request->header('upload-offset'); $uploadLenght = $request->header('upload-length'); $uploadName = $request->header('upload-name'); $numberOfChunks = $uploadLenght / self::CHUNKSIZE; $currentChunk = $uploadOffset / self::CHUNKSIZE; return $id; }
解决方法:获取PATCH请求的分片内容
FilePond的分片PATCH请求内容是以原始二进制数据流传递的,无法通过常规表单字段方法获取,需按以下方式处理:
读取分片原始内容
在update方法中,用$request->getContent()直接获取分片的二进制数据:$chunkContent = $request->getContent();完善分片存储与合并逻辑
将每个分片追加写入临时文件,全部上传完成后合并为最终文件:const CHUNKSIZE = 1048576; // 与前端chunkSize保持一致(1MB) public function update(Request $request, $id) { $uploadOffset = (int)$request->header('upload-offset'); $uploadLength = (int)$request->header('upload-length'); $uploadName = $request->header('upload-name'); // 临时文件路径,用上传ID确保唯一性 $tempFilePath = storage_path('app/temp/' . $id); // 创建临时目录(不存在则创建) if (!file_exists(dirname($tempFilePath))) { mkdir(dirname($tempFilePath), 0755, true); } // 定位到offset位置写入分片内容 $fileHandle = fopen($tempFilePath, 'c'); fseek($fileHandle, $uploadOffset); fwrite($fileHandle, $request->getContent()); fclose($fileHandle); // 检查是否所有分片上传完成 $currentSize = filesize($tempFilePath); if ($currentSize === $uploadLength) { // 移动临时文件到最终存储目录 $finalPath = storage_path('app/uploads/' . $uploadName); rename($tempFilePath, $finalPath); // 可添加数据库记录等后续逻辑 return response()->json(['status' => 'completed', 'path' => $finalPath]); } return response()->json(['status' => 'chunk_received'], 200); }修正前端FilePond配置
server.patch需指向包含上传ID的路由,确保分片请求能携带唯一标识:server: { url: '/upload', patch: "/:id", // 绑定上传ID参数 headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }, },配置正确的路由
确保路由支持POST(初始化上传)和PATCH(上传分片)请求:Route::post('/upload', [UploadController::class, 'store'])->name('upload.store'); Route::patch('/upload/{id}', [UploadController::class, 'update'])->name('upload.update');优化初始化请求处理
完善store方法,提前创建临时文件避免权限问题:public function store(Request $request) { if ($request->input('file') === '{}') { $uploadId = uniqid(); // 初始化空临时文件 $tempFilePath = storage_path('app/temp/' . $uploadId); touch($tempFilePath); return $uploadId; } // 非分片上传的处理逻辑(可选) return ''; }
内容的提问来源于stack exchange,提问作者Selajdin Bilali
相关产品推荐
相关产品推荐

