如何使用httr POST多部分/相关内容(适用于Google Drive API) [英] How to POST multipart/related content with httr (for Google Drive API)

查看:260
本文介绍了如何使用httr POST多部分/相关内容(适用于Google Drive API)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用httr将简单文件上传到Google云端硬盘。问题是,每个文件上传为无标题,我必须补丁元数据设置标题。 PATCH请求偶尔会失败。



根据

  res< -POST(
https://www.googleapis.com/upload/drive/v2/files?convert=true,
config (token = google_token),
body = list(y = upload_file(file))

id< -fromJSON(rawToChar(res $ content))$ id
if is.null(id))stop(上传失败)
url< -paste(
https://www.googleapis.com/drive/v2/files/,
id,
sep =

title< -strsplit(basename(file),\\。)[[1]] [1]
Sys .sleep(2)
res< -PATCH(url,
config(token = google_token),
body = paste('{title:',title,'}' ,sep =),
add_headers(Content-Type=application / json; charset = UTF-8)

stopifnot(res $ status_code == 200)
cat(id)

我想要做的就是这样:

  res< -POST(
https://www.googleapis.com/upload/drive/v2 / files?uploadType = multipart& convert = true,
config(token = google_token),
body = list(y = upload_file(file),
#add_headers(Content-Disposition =text / json),
json = toJSON(data.frame(title))
),
encode =multipart,
add_headers(Content-Type =multipart / related),
verbose()

输出我得到显示,各个部分的内容编码是错误的,并导致400错误:

   - > POST / upload / drive / v2 / files?uploadType = multipart& convert = true HTTP / 1.1 
- > User-Agent:curl / 7.19.7 Rcurl / 1.96.0 httr / 0.6.1
- >主持人:www.googleapis.com
- > Accept-Encoding:gzip
- >接受:application / json,text / xml,application / xml,* / *
- >授权:持票人ya29.ngGLGA9iiOrEFt0ycMkPw7CZq23e6Dgx3Syjt3SXwJaQuH4B6dkDdFXyIC6roij2se7Fs-Ue_A9lfw
- >内容长度:371
- >期望:100-继续
- >内容类型:多部分/相关; boundary = ---------------------------- 938934c053c6
- >
< - HTTP / 1.1 100继续
>> ------------------------------ 938934c053c6
>>内容处理:表单数据; NAME = Y; filename =db_biggest_tables.csv
>> Content-Type:application / octet-stream
>>

>>表行数据idx total_size idxfrac

>>
>> ------------------------------ 938934c053c6
>>内容处理:表单数据; name =json
>>
>> {title:db_biggest_tables}
>> ------------------------------ 938934c053c6--

< - HTTP / 1.1 400错误请求
< - Vary:Origin
< - Vary:X-Origin
< - Content-Type:application / json; charset = UTF-8
< - Content-Length:259
< - 日期:2015年6月26日星期五18:50:38 GMT
< - 服务器:UploadServer
< - 交替协议:443:quic,p = 1
< -

有没有什么办法可以正确设置各个部分的内容编码?例如,第二部分应该是text / json。

我已经通过R文档,Github上的Hadley的httr项目页面,以及一些一般的Google搜索。我找不到任何如何做分段上传和设置内容编码的例子。 解决方案

你应该能够使用 curl :: form_file 或其别名 httr :: upload_file 来做到这一点。另请参阅卷曲小插曲。以Google API文档为例:

  library(httr)

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

元数据< - tempfile()
writeLines(jsonlite :: toJSON(list(title = unbox(My file)),metadata)

#post
req< - POST(https: // $ http://httpbin.org/post,
body = list(
metadata = upload_file(元数据,type =application / json; charset = UTF-8),
media = upload_file (Content-Type=multipart / related),
verbose()
)$ b $,
),
add_headers b
取消链接(媒体)
取消链接(元数据)

是curl会自动为每个文件添加一个 Content-Disposition 头文件,这是 multipart / form-data 但不适用于 multipart / related 。在这种情况下,服务器可能会忽略这个多余的头文件。



现在没有办法在没有将内容写入文件的情况下完成这个任务。也许我们可以在未来的httr / curl版本中添加类似的东西,虽然这个还没有出现过。


I got simple file uploads to Google Drive working using httr. The problem is that every document is uploaded as "untitled", and I have to PATCH the metadata to set the title. The PATCH request occasionally fails.

According to the API, I ought to be able to do a multipart upload, allowing me to specify the title as part of the same POST request that uploads the file.

res<-POST(
  "https://www.googleapis.com/upload/drive/v2/files?convert=true",
  config(token=google_token),
  body=list(y=upload_file(file))
)
id<-fromJSON(rawToChar(res$content))$id
if(is.null(id)) stop("Upload failed")
url<-paste(
  "https://www.googleapis.com/drive/v2/files/",
  id,
  sep=""
)
title<-strsplit(basename(file), "\\.")[[1]][1]
Sys.sleep(2)
res<-PATCH(url,
  config(token=google_token),
  body=paste('{"title": "',title,'"}', sep = ""),
  add_headers("Content-Type" = "application/json; charset=UTF-8")
)
stopifnot(res$status_code==200)
cat(id)

What I'd like to do is something like this:

res<-POST(
  "https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart&convert=true",
  config(token=google_token),
  body=list(y=upload_file(file),
            #add_headers("Content-Disposition" = "text/json"),
            json=toJSON(data.frame(title))
  ),
  encode="multipart",
  add_headers("Content-Type" = "multipart/related"),
  verbose()
)

The output I get shows that the content encoding of the individual parts is wrong, and it results in a 400 error:

-> POST /upload/drive/v2/files?uploadType=multipart&convert=true HTTP/1.1
-> User-Agent: curl/7.19.7 Rcurl/1.96.0 httr/0.6.1
-> Host: www.googleapis.com
-> Accept-Encoding: gzip
-> Accept: application/json, text/xml, application/xml, */*
-> Authorization: Bearer ya29.ngGLGA9iiOrEFt0ycMkPw7CZq23e6Dgx3Syjt3SXwJaQuH4B6dkDdFXyIC6roij2se7Fs-Ue_A9lfw
-> Content-Length: 371
-> Expect: 100-continue
-> Content-Type: multipart/related; boundary=----------------------------938934c053c6
-> 
<- HTTP/1.1 100 Continue
>> ------------------------------938934c053c6
>> Content-Disposition: form-data; name="y"; filename="db_biggest_tables.csv"
>> Content-Type: application/octet-stream
>> 

>> table    rows    DATA    idx total_size  idxfrac

>> 
>> ------------------------------938934c053c6
>> Content-Disposition: form-data; name="json"
>> 
>> {"title":"db_biggest_tables"}
>> ------------------------------938934c053c6--

<- HTTP/1.1 400 Bad Request
<- Vary: Origin
<- Vary: X-Origin
<- Content-Type: application/json; charset=UTF-8
<- Content-Length: 259
<- Date: Fri, 26 Jun 2015 18:50:38 GMT
<- Server: UploadServer
<- Alternate-Protocol: 443:quic,p=1
<- 

Is there any way to set the content encoding properly for individual parts? The second part should be "text/json", for example.

I have been through R documentation, Hadley's httr project pages at Github, this site and some general googling. I can't find any examples of how to do a multipart upload and set content-encoding.

解决方案

You shoud be able to do this using curl::form_file or its alias httr::upload_file. See also the curl vignette. Following the example from the Google API doc:

library(httr)

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

metadata <- tempfile()
writeLines(jsonlite::toJSON(list(title = unbox("My file"))), metadata)

#post
req <- POST("https://httpbin.org/post",
  body = list(
    metadata = upload_file(metadata, type = "application/json; charset=UTF-8"),
    media = upload_file(media, type = "image/png")
  ),
  add_headers("Content-Type" = "multipart/related"),
  verbose()
)

unlink(media)
unlink(metadata)

The only difference here is that curl will automatically add a Content-Disposition header for each file, which is required for multipart/form-data but not for multipart/related. The server will probably just ignore this redundant header in this case.

For now there is no way to accomplish this without writing the content to a file. Perhaps we could add something like that in a future version of httr/curl, although this has not come up before.

这篇关于如何使用httr POST多部分/相关内容(适用于Google Drive API)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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