Google Drive v3 API resumable上传返回200但云端无文件
问题成因
- 核心原因:你当前使用服务账号密钥做认证,服务账号是Google分配的独立虚拟账号,拥有专属的独立Drive存储空间,你上传的文件默认存储在服务账号的私有Drive空间内,并非你登录网页版使用的个人账号空间,因此用个人账号登录无法看到文件。
- 断点续传请求逻辑不符合API规范:
X-Upload-Content-Type、X-Upload-Content-Length两个头属于初始化上传会话阶段的参数,你错误放到了上传文件内容的请求里;且上传文件内容阶段错误将Content-Type设为application/json,未使用正确的PUT请求方法、也未携带必填的Content-Range头,当前返回200属于接口兼容的异常场景,存在上传文件损坏的风险。 - 初始化上传请求未指定
parents参数:未指定文件存放的父目录ID时,文件会默认存到当前认证账号的根目录,若账号配置了根目录文件过滤规则,也会出现找不到文件的情况。
修复方案
- 解决文件归属问题
- 若要将文件上传到个人账号的Drive空间:在初始化上传的请求体中添加
parents字段,值为你个人Drive中目标文件夹的ID数组,提前将该目标文件夹共享给服务账号邮箱(即CREDS文件内的client_email字段值),授予编辑权限即可。 - 若不需要用服务账号,直接替换认证逻辑为个人账号OAuth2.0授权,使用个人账号的凭证发起请求,文件会直接上传到个人账号空间。
- 若要将文件上传到个人账号的Drive空间:在初始化上传的请求体中添加
- 修正断点续传请求逻辑
- 第一步:发起resumable初始化请求时,在请求头携带
X-Upload-Content-Type: audio/mp3、X-Upload-Content-Length: {实际文件总字节数},请求体中补充parents参数,从返回的响应头Location中拿到断点续传的会话URI,不要自行拼接续传地址。 - 第二步:上传文件内容时,将请求头的
Content-Type改为audio/mp3,移除错误放置的X-Upload-*头,携带Content-Range: bytes 0-{文件总字节数-1}/{文件总字节数}(全量上传场景),Content-Length设为本次上传的文件内容字节数,使用PUT方法发起请求,请求体放文件二进制内容即可。
- 第一步:发起resumable初始化请求时,在请求头携带
修正后的核心代码示例
// 提前拿到Zoom文件的实际大小 const fileSize = Number(headers["zoom-file-size"]); // 初始化上传会话(修正后) const initialRes = await client.request({ url: "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable", method: "POST", headers: { "Content-Type": "application/json; charset=UTF-8", "X-Upload-Content-Type": "audio/mp3", "X-Upload-Content-Length": fileSize, }, data: { name: `${job.data.callId}.mp3`, parents: ["你个人Drive里的目标文件夹ID"] // 提前给服务账号开这个文件夹的编辑权限 }, }); // 从响应头拿续传会话URI const uploadSessionUri = initialRes.headers.location; // 上传文件内容(修正后) const response = await client.request({ url: uploadSessionUri, headers: { "Content-Type": "audio/mp3", "Content-Length": data.length, "Content-Range": `bytes 0-${data.length - 1}/${fileSize}` }, method: "PUT", data: Buffer.from(data), });
验证技巧:上传成功拿到文件ID后,直接访问
https://drive.google.com/file/d/{文件ID}/view,如果能正常打开预览,说明文件上传成功,再到指定的父目录下即可找到对应文件。
内容的提问来源于stack exchange,提问作者Koki Senpai
相关产品推荐
相关产品推荐

