Ruby 通过API上载本地CSV失败

Ruby 通过API上载本地CSV失败,ruby,google-bigquery,Ruby,Google Bigquery,我使用的是官方的Google Ruby gem,虽然到目前为止,我尝试的其他一切都很好(包括列出项目、数据集和表,以及创建表),但启动加载作业失败,JSON错误响应中出现以下错误: "Job configuration must contain exactly one job-specific configuration object (e.g., query, load, extract, spreadsheetExtract), but there were 0: " 我创建的主体字符串如

我使用的是官方的Google Ruby gem,虽然到目前为止,我尝试的其他一切都很好(包括列出项目、数据集和表,以及创建表),但启动加载作业失败,JSON错误响应中出现以下错误:

"Job configuration must contain exactly one job-specific configuration object (e.g., query, load, extract, spreadsheetExtract), but there were 0: "
我创建的主体字符串如下所示:

--xxx
Content-Type: application/json; charset=UTF-8
{"configuration":{"load":{"destinationTable":{"projectId":"mycompany.com:projectId","datasetId":"all_events","tableId":"install"},"createDisposition":"CREATE_NEVER","writeDisposition":"WRITE_APPEND"}}}
--xxx
Content-Type: application/octet-stream
test,second,1234,6789,83838
--xxx
param_hash = { api_method: big_query_api.jobs.insert }
param_hash[:parameters] = {'projectId' => project_id, 'uploadType' => 'multipart'}
param_hash[:body] = body
param_hash[:headers] = {'Content-Type' => "multipart/related; boundary=#{multipart_boundary}"}
我以前为该数据创建了
install
表,其中包含适当的模式,因此这不应该是问题所在

最后,为了完整起见,这里是我用来发出请求的实际代码片段(这是一个更大类中的两个方法):

有什么想法吗

对下面的答案进行添加,以使此代码正常工作

请注意,上面的#multipart_boundary方法返回时,前面已经加了“---”。这是一个问题,因为设置边界头(在param散列中)将导致“-xxx”,而实际上我们需要“xxx”

此外,这个gem的文档非常粗糙,因为在修复了我的换行问题(根据@jcondit的回答)之后,我遇到了一个关于上传到错误URL的新错误。这是因为您需要添加:

'uploadType' => 'multipart'
发送到参数,以便将请求发送到正确的URL

因此,最终的param_散列(同样,在修复换行符和边界ISSE之后)看起来如下所示:

--xxx
Content-Type: application/json; charset=UTF-8
{"configuration":{"load":{"destinationTable":{"projectId":"mycompany.com:projectId","datasetId":"all_events","tableId":"install"},"createDisposition":"CREATE_NEVER","writeDisposition":"WRITE_APPEND"}}}
--xxx
Content-Type: application/octet-stream
test,second,1234,6789,83838
--xxx
param_hash = { api_method: big_query_api.jobs.insert }
param_hash[:parameters] = {'projectId' => project_id, 'uploadType' => 'multipart'}
param_hash[:body] = body
param_hash[:headers] = {'Content-Type' => "multipart/related; boundary=#{multipart_boundary}"}

您的http请求格式不正确——bigquery根本无法将其识别为加载作业。我在路上吃晚饭,所以我不能做任何更深的调查,但希望这给你一个指针继续下去。 我仔细看了一下,我看不出你的要求有什么问题。一个建议是尝试在BigQueryUI中执行相同的加载,并使用chrome工具->开发者工具/网络选项卡查看发送的RPC

如果使用虚拟csv文件执行此操作,则会得到:

--yql9f05215ct
Content-Type: application/json; charset=utf-8

{"jobReference":{"projectId":"helixdata2"},"configuration":{"load":{"destinationTable":{"projectId":"helixdata2","datasetId":"lotsOdata","tableId":"import"}}}}
--yql9f05215ct
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64

YSxiLGMKYyxkLGUKZixnLGgK
--yql9f05215ct--

您需要在每个MIME部分的头和每个MIME部分的主体之间插入额外的换行符。请求的主体应如下所示:

--xxx
Content-Type: application/json; charset=UTF-8

{"configuration":{"load":{"destinationTable":{"projectId":"mycompany.com:projectId","datasetId":"all_events","tableId":"install"},"createDisposition":"CREATE_NEVER","writeDisposition":"WRITE_APPEND"}}}
--xxx
Content-Type: application/octet-stream

test,second,1234,6789,83838
--xxx--
请注意每个部分中内容类型标题后的额外换行符


另外,不要忘记,最后的边界分隔符有一个尾随符--附加在它后面。

3个区别我看到:-jobReference键/值哈希-内容传输编码:base64-projectId只是名称,而不是我尝试了两种方法的projectId并添加到jobReference和内容传输中的完整路径。两者都失败了。请参阅下面的注释。--xxx内容类型:application/json;charset=UTF-8{“jobReference”:{“projectId”:“wizards”},“configuration”:{“load”:{“destinationTable”:{“projectId”:“wizards”,“datasetId”:“all_events”,“tableId”:“install”},“createDisposition”:“CREATE_NEVER”,“writeDisposition”:“WRITE_APPEND”}}--xxx内容类型:应用程序/八位组流内容传输编码:base64测试,秒,1234678983838--xxx--xxx内容类型:application/json;charset=UTF-8{“jobReference”:{“projectId”:“OrangeOrarmy.com:wizards”},“configuration”:{“load”:{“destinationTable”:{“projectId”:“OrangeOrarmy.com:wizards”;“datasetId”:“all_events”,“tableId”:“install”},“createDisposition”:“CREATE_NEVER”,“writeDisposition”:“WRITE_APPEND”}}--xxx内容类型:应用程序/八位字节流内容传输编码:base64测试,秒,1234678983838--xxx感谢您!两年后,这帮了我的忙。找不到我需要在参数中包含“uploadType”。