Dropzone.js分块上传后,如何用Google Drive API PHP合并文件?是否可行?
需求可行,调整上传逻辑即可实现
你的问题出在当前代码每次调用addFile都会创建一个新的Google Drive文件,没有利用resumable upload的分块续传能力。要合并块成单个文件,需要遵循Google Drive可续传上传的流程:
1. 初始化可续传上传会话
在收到第一个文件块时,先创建一个空的上传会话,获取续传URL,这个URL要和当前上传的文件绑定(比如存在用户会话、Redis或数据库中):
public function initResumableUpload($filename, $description = '') { $file = new \Google\Service\Drive\DriveFile(); $file->setName($filename); $file->setParents([$_ENV['FOLDER_ID']]); $file->setDescription($description); // 初始化可续传上传,不发送文件内容 $request = $this->driveService->files->create( $file, [ 'mimeType' => 'video/mp4', // 直接设置最终的MIME类型 'uploadType' => 'resumable' ] ); // 获取续传URL,需要保存下来供后续块上传使用 $resumableUrl = $request->getResumeUri(); return $resumableUrl; }
2. 上传单个文件块
对于每个文件块(包括第一个),使用保存的续传URL,指定当前块的起始字节位置,发送块内容:
public function uploadFileChunk($resumableUrl, $chunkContent, $startByte, $totalFileSize) { $chunkSize = strlen($chunkContent); $endByte = $startByte + $chunkSize - 1; // 设置请求头,指定字节范围 $headers = [ 'Content-Range' => "bytes $startByte-$endByte/$totalFileSize", 'Content-Type' => 'application/octet-stream' ]; // 发送块内容到续传URL $client = $this->driveService->getClient(); $response = $client->put($resumableUrl, [ 'headers' => $headers, 'body' => $chunkContent ]); // 如果响应状态是200或201,说明上传完成;206表示还有块需要上传 if ($response->getStatusCode() === 200 || $response->getStatusCode() === 201) { $fileId = json_decode($response->getBody())->id; return sprintf('https://drive.google.com/file/d/%s/view?usp=sharing', $fileId); } elseif ($response->getStatusCode() === 206) { // 可以返回当前已上传的字节位置,用于验证 return $response->getHeaderLine('Range'); } else { throw new Exception("上传块失败: " . $response->getStatusCode()); } }
3. 前端配合逻辑
- Dropzone分块上传时,需要传递每个块的
startByte(当前块的起始字节)和totalFileSize(整个文件的总大小)到PHP后端。 - 第一个块上传前,先调用
initResumableUpload获取续传URL,后续所有块都使用这个URL上传。 - 确保块的上传顺序正确,Dropzone默认按顺序上传分块,可直接依赖该特性。
关键注意事项
- 续传URL有效期通常为1周,足够完成大文件上传。
- 每个块大小建议在256KB到5MB之间(Google官方推荐),避免块过小导致请求冗余,或块过大易上传失败。
- 若某个块上传失败,可通过续传URL重新上传该块,无需从头开始整个文件的上传。
内容的提问来源于stack exchange,提问作者user979331
相关产品推荐
相关产品推荐

