如何使用原生JavaScript向谷歌云端硬盘分块上传录制中的视频
Chrome扩展录屏实时上传谷歌云端硬盘实现方案
你当前使用的uploadType=multipart是谷歌云盘的一次性上传接口,仅支持传输完整文件,无法实现边录边传的效果,需改用**可恢复上传(Resumable Upload)**接口改造,具体实现逻辑如下:
- 录屏启动时先创建上传会话
录屏开始前就调用云盘接口初始化可恢复上传会话,拿到后续可以追加分片的会话地址,同时预先设置好文件名称、父文件夹等元数据,示例代码如下:
// 初始化可恢复上传会话 function initResumableUpload(accessToken, folderId) { const metadata = { name: Date.now() + '.mp4', mimeType: 'video/mp4', parents: [folderId], }; return new Promise((resolve) => { const xhr = new XMLHttpRequest(); xhr.open('POST', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable'); xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.onload = () => { // 返回上传会话地址 resolve(xhr.getResponseHeader('Location')); }; xhr.send(JSON.stringify(metadata)); }); }
- 录屏过程中实时上传分片
配置MediaRecorder的timeslice参数,让它每隔固定毫秒数输出一个blob分片,每拿到一个新分片就往之前拿到的会话地址发送PATCH请求追加数据,注意要正确设置Content-Range头标明当前分片的字节位置:
let uploadSessionUrl = ''; let currentUploadOffset = 0; let recordedBlobs = []; // 初始化录屏 async function startRecording() { // 先初始化上传会话 uploadSessionUrl = await initResumableUpload(accessToken, folderId); const stream = await navigator.mediaDevices.getDisplayMedia({ video: true }); const mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/mp4' }); // 每1秒输出一个分片,可根据需要调整间隔 mediaRecorder.start(1000); mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) { recordedBlobs.push(e.data); // 直接上传当前分片 uploadChunk(e.data); } }; } // 上传单个分片 function uploadChunk(chunk) { const chunkSize = chunk.size; const xhr = new XMLHttpRequest(); xhr.open('PATCH', uploadSessionUrl); xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken); xhr.setRequestHeader('Content-Range', `bytes ${currentUploadOffset}-${currentUploadOffset + chunkSize - 1}/*`); xhr.setRequestHeader('Content-Length', chunkSize); xhr.onload = () => { currentUploadOffset += chunkSize; }; xhr.send(chunk); }
- 录屏停止时完成上传
录屏停止后发送最后一个请求,告知云盘所有分片已传输完成,触发云盘拼接文件:
function finishUpload() { const xhr = new XMLHttpRequest(); xhr.open('PATCH', uploadSessionUrl); xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken); xhr.setRequestHeader('Content-Range', `bytes */${currentUploadOffset}`); xhr.responseType = 'json'; xhr.onload = () => { // xhr.response.id 即为上传完成的文件ID console.log('上传完成,文件ID:', xhr.response.id); }; xhr.send(); }
注意事项:如果中途出现网络错误导致分片上传失败,可以向会话地址发送一个不带请求体的GET请求,获取云盘当前已接收的字节偏移量,从断点位置继续上传即可,不需要重新传整个文件。
内容的提问来源于stack exchange,提问作者GMAC
相关产品推荐
相关产品推荐

