file('file'); if (!$file) { return json(['code' => 400, 'msg' => '未找到分片文件'], 400); } try { $data = $this->disk($request->post('disk', Storage::MODE_LOCAL))->uploadChunk( $file, (string) $request->post('file_id', ''), (int) $request->post('chunk_index', 0), (string) $request->post('chunk_md5', ''), ); return json(['code' => 0, 'msg' => 'ok', 'data' => $data]); } catch (\Throwable $e) { return json(['code' => 500, 'msg' => $e->getMessage()], 500); } } /** * 断点续传进度查询 * GET /upload/progress?file_id=xxx&total_chunks=3&disk=local */ public function progress(Request $request) { try { $data = $this->disk($request->get('disk', Storage::MODE_LOCAL))->chunkProgress( (string) $request->get('file_id', ''), (int) $request->get('total_chunks', 0), ); return json(['code' => 0, 'msg' => 'ok', 'data' => $data]); } catch (\Throwable $e) { return json(['code' => 500, 'msg' => $e->getMessage()], 500); } } /** * 合并全部分片 * POST /upload/merge form-data: file_id、total_chunks、file_name(完整文件名,如 video.mp4)、disk(可选) * * 云端合并建议传 file_hash(整文件散列)作为最终对象名;同时可传 mime_type * (云端无法探测 MIME,否则默认 application/octet-stream) */ public function merge(Request $request) { try { $options = []; $fileHash = (string) $request->post('file_hash', ''); if ('' !== $fileHash) { $options['file_hash'] = $fileHash; } $mimeType = (string) $request->post('mime_type', ''); if ('' !== $mimeType) { $options['mime_type'] = $mimeType; } $data = $this->disk($request->post('disk', Storage::MODE_LOCAL))->mergeChunk( (string) $request->post('file_id', ''), (int) $request->post('total_chunks', 0), (string) $request->post('file_name', ''), $options, ); return json(['code' => 0, 'msg' => 'ok', 'data' => $data]); } catch (\Throwable $e) { return json(['code' => 500, 'msg' => $e->getMessage()], 500); } } /** * 按参数解析存储 disk,非法值抛异常 */ private function disk(string $disk) { if (!in_array($disk, self::DISKS, true)) { throw new \InvalidArgumentException('不支持的 disk:' . $disk); } return Storage::disk($disk, false); } }