如何限制Google Drive异步断点续传的并发上传数量?
解决Google Drive分片上传并发控制问题
你不需要修改外部的resumableupload_js.min.js,只需要调整自己的上传逻辑,通过串行处理批次+Promise监听上传完成来实现每次仅并发10个文件,完成一批再启动下一批。
核心修改点:
- 放弃原来的for循环直接启动所有批次,改用递归函数串行处理每个批次
- 将单个文件的上传过程包装为Promise,通过
Promise.all监听整个批次的上传完成状态 - 只有当前批次的所有文件上传完成后,才启动下一个批次的上传
修改后的完整代码:
<input type="file" id="file" multiple="true" /> <input type="button" onclick="run()" value="Upload" /> <div id="progress"></div> <script src="https://cdn.jsdelivr.net/gh/tanaikech/ResumableUploadForGoogleDrive_js@master/resumableupload_js.min.js"></script> <script> function run() { google.script.run.withSuccessHandler(accessToken => ResumableUploadForGoogleDrive(accessToken)).getAuth(); } function ResumableUploadForGoogleDrive(accessToken) { const f = document.getElementById("file"); const chunkSize = 10; const files = Array.from(f.files); const totalChunks = Math.ceil(files.length / chunkSize); // 递归处理批次的函数 async function processBatch(batchIndex) { if (batchIndex >= totalChunks) return; // 所有批次处理完成 const startIndex = batchIndex * chunkSize; const endIndex = startIndex + chunkSize; const currentBatch = files.slice(startIndex, endIndex); console.log(`开始处理第${batchIndex+1}批,共${currentBatch.length}个文件`); // 将每个文件的上传包装为Promise const uploadPromises = currentBatch.map((file, idx) => { return new Promise((resolve, reject) => { if (!file) return resolve(); let fr = new FileReader(); fr.fileName = file.name; fr.fileSize = file.size; fr.fileType = file.type; fr.readAsArrayBuffer(file); fr.onload = e => { var id = "p" + (startIndex + idx + 1); var div = document.createElement("div"); div.id = id; document.getElementById("progress").appendChild(div); document.getElementById(id).innerHTML = "Initializing."; const resource = { fileName: fr.fileName, fileSize: fr.fileSize, fileType: fr.fileType, fileBuffer: fr.result, accessToken: accessToken, folderId: "<insert folder ID>" }; const ru = new ResumableUploadToGoogleDrive(); ru.Do(resource, function (res, err) { if (err) { console.error(err); document.getElementById(id).innerText = `上传失败 (${fr.fileName})`; return reject(err); } let msg = ""; if (res.status == "Uploading") { msg = Math.round((res.progressNumber.current / res.progressNumber.end) * 100) + "% (" + fr.fileName + ")"; } else { msg = res.status + " (" + fr.fileName + ")"; if (res.status === "Done") { resolve(); // 只有上传完成时才resolve Promise } } document.getElementById(id).innerText = msg; }); }; fr.onerror = () => { reject(new Error(`读取文件失败: ${file.name}`)); }; }); }); // 等待当前批次所有文件上传完成 await Promise.all(uploadPromises); console.log(`第${batchIndex+1}批处理完成`); // 处理下一个批次 await processBatch(batchIndex + 1); } // 启动第一个批次 processBatch(0).catch(err => console.error("上传过程出错:", err)); }; </script>
关键逻辑说明:
- Promise包装上传:每个文件的上传流程被包装成Promise,只有当上传状态变为
Done时才会resolve,确保能准确监听每个文件的完成事件。 - 递归批次处理:
processBatch函数负责处理单个批次,通过await Promise.all(uploadPromises)等待当前批次所有文件完成后,再递归调用自身处理下一个批次。 - 避免全量并发:取消了原来的for循环直接启动所有批次的逻辑,改为串行触发批次,从根本上控制了并发数为每批10个。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

