Google Apps Script调用BigQuery.jobs.insert遇空响应错误求助
解决Google Apps Script上传CSV到BigQuery时的"Empty response"错误
针对你遇到的前两次执行正常、第三次出现API call to bigquery.jobs.insert failed with error: Empty response的问题,以下是几种常见原因和对应的解决手段:
1. 临时API服务波动或请求超时
BigQuery API偶尔会出现临时的网络连接问题,尤其是在Apps Script的客户端环境中,这类空响应通常是一次性的。
解决办法:添加重试机制
在请求失败后自动重试几次,大概率能绕过临时故障。修改你的CargaBigQuery函数,加入重试逻辑:
function CargaBigQuery(BQDatasetId, BQTableId, BQFileBlob) { const projectId = 'xxxxxx'; BQFileBlob.setContentType('application/octet-stream'); const job = { configuration: { load: { destinationTable: { projectId: projectId, datasetId: BQDatasetId, tableId: BQTableId }, skip_leading_rows: 1, field_delimiter: ';', encoding: 'ISO-8859-1', allow_jagged_rows: true, allow_quoted_new_lines: true, autodetect: false, ignore_unknown_values: false, source_format: 'CSV', write_disposition: 'WRITE_APPEND', max_bad_records: 0 } } }; const maxRetries = 3; let retryCount = 0; while (retryCount < maxRetries) { try { const jobResult = BigQuery.Jobs.insert(job, projectId, BQFileBlob); console.log(`\t\tLoading status: ${jobResult.status.state}`); return true; } catch (err) { retryCount++; console.log(`\t\tError (attempt ${retryCount}): ${err}`); if (retryCount >= maxRetries) { console.log('\t\tMax retries reached, failing.'); return false; } Utilities.sleep(2000); // 间隔2秒重试 } } }
2. 解压后的Blob对象状态异常
虽然使用相同的ZIP文件,但第三次执行时,解压得到的Blob可能出现隐性的内容或元数据损坏,比如编码丢失、内容截断等。
解决办法:验证并重新构建Blob
在调用上传函数前,先验证Blob的完整性,再重新构建Blob确保编码正确:
var Escopo = {}; Escopo.DatasetId = 'aaaaaaaaa'; Escopo.TableId = 'bbbbbbbbb'; FileID = 'google drive .zip file ID'; var ArqZip = DriveApp.getFileById(FileID).getBlob(); ArqZip.setContentType("application/zip"); var ArqUnZipped = Utilities.unzip(ArqZip); var originalCsvBlob = ArqUnZipped[0]; // 验证Blob大小,确认和前两次执行的输出一致 console.log(`CSV Blob size: ${originalCsvBlob.getSize()} bytes`); // 重新构建Blob,确保编码为ISO-8859-1 var fixedCsvBlob = Utilities.newBlob( originalCsvBlob.getDataAsString('ISO-8859-1'), 'application/octet-stream', originalCsvBlob.getName() ); var RetornoBQ = CargaBigQuery(Escopo.DatasetId, Escopo.TableId, fixedCsvBlob);
3. BigQuery作业并发限制或资源冲突
前两次提交的作业可能仍在后台运行,第三次提交时触发了BigQuery的并发作业限制,导致服务端返回空响应。
解决办法:检查作业状态并避免并发提交
- 登录BigQuery控制台,进入作业历史,查看前两次作业是否已经完成;
- 如果是循环执行场景,修改代码等待前一个作业完成后再提交新作业:
// 在插入作业后,轮询直到作业完成 function waitForJobCompletion(jobId, projectId) { let jobStatus; do { jobStatus = BigQuery.Jobs.get(projectId, jobId).status; if (jobStatus.state === 'DONE') break; Utilities.sleep(5000); // 每5秒检查一次 } while (true); return jobStatus; } // 修改CargaBigQuery函数,返回jobId以便跟踪 function CargaBigQuery(BQDatasetId, BQTableId, BQFileBlob) { // ... 原有配置代码 ... try { const jobResult = BigQuery.Jobs.insert(job, projectId, BQFileBlob); console.log(`\t\tLoading status: ${jobResult.status.state}`); waitForJobCompletion(jobResult.jobReference.jobId, projectId); // 等待完成 return true; } catch (err) { // ... 原有错误处理 ... } }
4. Apps Script执行环境缓存问题
Apps Script的执行环境可能缓存了异常的对象或状态,导致第三次执行时出现问题。
解决办法:重置执行环境
- 修改脚本代码后保存,重新运行;
- 在脚本编辑器中点击运行 -> 授权(即使权限未修改,重新授权会重置执行环境);
- 将解压和上传逻辑拆分为独立函数,避免对象被缓存。
内容的提问来源于stack exchange,提问作者MFStella
相关产品推荐
相关产品推荐

