如何发布多部分二进制& httr非二进制文件(用于Salesforce API) [英] How to POST multipart binary & non-binary with httr (for Salesforce API)

查看:136
本文介绍了如何发布多部分二进制& httr非二进制文件(用于Salesforce API)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 httr 将文件发布到 Salesforce的REST API 。我以为这个SO问题可能会解决,但似乎没有。我有一种预感,这是因为Saleforce想要一个非二进制部分,并且 upload_file 创建了一个 form_file 类的对象,作为二进制文件处理,但也许有人有其他解释/解决方案...

I'm having some trouble using httr to POST a file to Salesforce's REST API. I thought this SO question might take care of it, but didn't seem to. I have a hunch that this is because Saleforce wants a non-binary part and upload_file creates an object of class form_file that's handled as a binary, but maybe someone has an alternate explanation/solution...

Salesforce要求以下curl请求插入新文档:

Salesforce asks for the following curl request to insert a new document:

curl https://yourInstance.salesforce.com/services/data/v23.0/sobjects/Document/ -H
"Authorization: Bearer token" -H "Content-Type: multipart/form-data;
boundary=\"boundary_string\"" --data-binary @newdocument.json

newdocument.json 看起来像这样:

--boundary_string
Content-Disposition: form-data; name="entity_document";
Content-Type: application/json
{
"Description" : "Marketing brochure for Q1 2011",
"Keywords" : "marketing,sales,update",
"FolderId" : "005D0000001GiU7",
"Name" : "Marketing Brochure Q1",
"Type" : "pdf"
}
--boundary_string
Content-Type: application/pdf
Content-Disposition: form-data; name="Body"; filename="2011Q1MktgBrochure.pdf"
Binary data goes here.
--boundary_string--

如果我尝试使用@Jeroen的答案生成类似的输出作为有用的指南,我收到一个错误的请求错误:

If I try to generate a similar output using @Jeroen's answer as a helpful guide, I get a Bad Request error:

library(httr)
library(jsonlite)

url <- "https://[Salesforce Instance]/services/data/v39.0/sobjects/Document/"
header <- add_headers(c(Authorization = "Bearer [Salesforce Key]"))

media <- tempfile()
png(media, width = 800, height = 600)
plot(cars)
dev.off()

metadata <- tempfile()
x <- data.frame(FolderId="a0a1300000ZG7u3", Name="test.png") #Salesforce Record ID and file name
json <- toJSON(unbox(x), pretty=T)
writeLines(json, metadata)

body <- list(entity_document = upload_file(metadata, type = "application/json; charset=UTF-8"), 
             Body = upload_file(media, type = "image/png"))


req <- POST(url, header, verbose(), body = body)

(详细输出)

-> POST /services/data/v39.0/sobjects/Document/ HTTP/1.1
-> Host: [Salesforce Instance]
-> User-Agent: libcurl/7.51.0 r-curl/2.3 httr/1.2.1.9000
-> Accept-Encoding: gzip, deflate
-> Accept: application/json, text/xml, application/xml, */*
-> Authorization: Bearer [Salesforce Key]
-> Content-Length: 3720
-> Expect: 100-continue
-> Content-Type: multipart/form-data; boundary=------------------------6525413b2350e313
-> 
<- HTTP/1.1 100 Continue
>> --------------------------6525413b2350e313
>> Content-Disposition: form-data; name="entity_document"; filename="file1510059b5200f"
>> Content-Type: application/json
>> 

>> {
>>     "FolderId": "a0a1300000ZG7u3",
>>     "Name": "test.png"
>>   }

>> 
>> --------------------------6525413b2350e313
>> Content-Disposition: form-data; name="Body"; filename="file151001ac96950"
>> Content-Type: image/png
>> 

>> ‰PNG
>> 

>> 
>> --------------------------6525413b2350e313--

<- HTTP/1.1 400 Bad Request

除了第一部分中的文件名外,这与所需的输出非常接近,但是Salesforce返回消息:

with the exception of the filename in the first part, this is pretty close to the desired output, but Salesforce returns the message:

content(req)

[[1]]
[[1]]$message
[1] "Cannot include more than one binary part"

[[1]]$errorCode
[1] "INVALID_MULTIPART_REQUEST"

我尝试使用json,但收到的Bad Request稍有不同:

I tried with just the json but get a slightly different Bad Request:

body <- list(entity_document= json, 
             Body = upload_file(media, type = "image/png"))

-> Content-Type: multipart/form-data; boundary=------------------------ecbd3787f083e4b1
-> 
<- HTTP/1.1 100 Continue
>> --------------------------ecbd3787f083e4b1
>> Content-Disposition: form-data; name="entity_document"
>> 
>> {
>>     "FolderId": "a0a1300000ZG7u3",
>>     "Name": "test.png"
>>   }
>> --------------------------ecbd3787f083e4b1
>> Content-Disposition: form-data; name="Body"; filename="file151001ac96950"
>> Content-Type: image/png
>> 

>> ‰PNG
>> 

>> 
>> --------------------------ecbd3787f083e4b1--

content(req)

[[1]]
[[1]]$message
[1] "Multipart message must include a non-binary part"

[[1]]$errorCode
[1] "INVALID_MULTIPART_REQUEST"

深入研究细节,在我看来 curl 如果使用 upload_file 读取或发布二进制格式的元数据文件,或者如果我将其作为字符发布,则以内容类型发布json。这是唯一的问题吗?如果是这样,是否有任何方法可以修改处理程序以接受内容类型?

Digging into the details, it seems to me that curl either reads and posts the metadata file as a binary if I use upload_file or posts the json without the content type if I post it as character. Is this the only issue? And if so, is there any way to modify the handler to accept the content type?

任何帮助都是值得的!

推荐答案

以下是OP尝试执行的操作的完整示例。

Here is a complete and working example of what the OP was trying to do.

library(httr)

# JSON formatted metadata
x <- list(a = 1, b = 2)

# PNG media
media <- tempfile()
png(media, width = 800, height = 600)
plot(cars)
dev.off()

# Construct multipart body
#   Note the use of form_data() and form_file() which allow 
#    the user to specify the content type of each part
body <- list(
  metadata = curl::form_data(toJSON(x), type = "application/json"),
  media = curl::form_file(media, type = mime::guess_type(media))
)

POST(url, body, encode = "multipart")

这篇关于如何发布多部分二进制&amp; httr非二进制文件(用于Salesforce API)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆