如何与改造发送的multipart / form-data的?multipart、form、data

由网友(独行)分享简介:我想发从文章和 Android版的客户端向REST服务器。这里是的的Python 的从服务器模型:I want to send an Article from and Android client to a REST server. Here is the Python model from the server:...

我想发从文章和 Android版的客户端向REST服务器。这里是的的Python 的从服务器模型:

I want to send an Article from and Android client to a REST server. Here is the Python model from the server:

class Article(models.Model):
    author = models.CharField(max_length=256, blank=False)
    photo = models.ImageField()

下面的接口描述前执行:

The following interface describes the former implementation:

@POST("/api/v1/articles/")
public Observable<CreateArticleResponse> createArticle(
        @Body Article article
);

现在我想发送的图像与文章的数据。该照片不是一部分的文章的模型上的的Andr​​oid 的客户端。

Now I want to send an image with the Article data. The photo is not part of the Article model on the Android client.

@Multipart
@POST("/api/v1/articles/")
public Observable<CreateArticleResponse> createArticle(
        @Part("article") Article article,
        @Part("photo") TypedFile photo
);

API是prepared并试验成功的卷曲的。

$ curl -vX POST http://localhost:8000/api/v1/articles/ 
    -H "Content-Type: multipart/form-data" 
    -H "Accept:application/json" 
    -F "author=cURL" 
    -F "photo=@/home/user/Desktop/article-photo.png"

当我通过发送数据createArticle()在 Android版的客户端收到一条 HTTP 400 状态,说明在字段是必需/缺少

When I send data through createArticle() from the Android client I receive an HTTP 400 status stating that the fields are required/missing.

D  <--- HTTP 400 http://192.168.1.1/articles/ (2670ms)
D  Date: Mon, 20 Apr 2015 12:00:00 GMT
D  Server: WSGIServer/0.1 Python/2.7.8
D  Vary: Accept, Cookie
D  X-Frame-Options: SAMEORIGIN
D  Content-Type: application/json
D  Allow: GET, POST, HEAD, OPTIONS
D  OkHttp-Selected-Protocol: http/1.0
D  OkHttp-Sent-Millis: 1429545450469
D  OkHttp-Received-Millis: 1429545453120
D  {"author":["This field is required."],"photo":["No file was submitted."]}
D  <--- END HTTP (166-byte body)
E  400 BAD REQUEST

这是被接收为 request.data 服务器端:

This is what is received as request.data on the server side:

ipdb> print request.data  
  <QueryDict: {u'article': [u'{"author":"me"}'], 
  u'photo': [<TemporaryUploadedFile: IMG_1759215522.jpg 
  (multipart/form-data)>]}>

如何转换的文章的在一个多对象符合数据类型?我读的的改造的可能允许使用的变频器了解这一点。它应该是一个实现了 retrofit.mime.TypedOutput 据我了解的的文档。

How can convert the Article object in a multipart conform data type? I read that Retrofit might allow to use Converters for this. It should be something that implements a retrofit.mime.TypedOutput as far as I understood for the documentation.

多部分零件使用 RestAdapter 的转换器,也可以实施 TypedOutput 来处理自己的序列化。

Multipart parts use the RestAdapter's converter or they can implement TypedOutput to handle their own serialization. HTML 4.01规范 - 表单提交 - 的multipart / form-data的 改造注释类型部分文档 Upload与改造以JSON多部分的图像数据? REST - HTTP多部分后用JSON 改造多部分上传图片失败 改造问题#178:创建手册与改造发送文件 改造问题#531:通过POST /多部分 问题上传文件 改造问题#658:不能与图像使用多 在当前发送字符串参数 改造问题#662:在单个请求改造形式恩codeD和多

Related

HTML 4.01 Specification - Form submission - multipart/form-data Retrofit Annotation Type Part documentation Upload multipart image data in JSON with Retrofit? REST - HTTP Post Multipart with JSON Retrofit Multipart Upload Image failed Retrofit issue #178: Create manual for sending files with retrofit Retrofit issue #531: Problem uploading file via POST/Multipart Retrofit issue #658: Not able to send string parameters with image when using Multipart Retrofit issue #662: Retrofit Form Encoded and Multipart in single request

推荐答案

根据您的卷曲的要求,你要创建水木清华这样的:

According to your curl request you are trying to create smth like this:

POST http://localhost:8000/api/v1/articles/ HTTP/1.1
User-Agent: curl/7.30.0
Host: localhost
Connection: Keep-Alive
Accept: application/json
Content-Length: 183431
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------23473c7acabb

------------------------------23473c7acabb
Content-Disposition: form-data; name="author"

cURL
------------------------------23473c7acabb
Content-Disposition: form-data; name="photo"; filename="article-photo.png"
Content-Type: application/octet-stream

‰PNG

<!RAW BYTES HERE!>

MUUÕ+4qUUU¯°WUUU¿×ß¿þ Naa…k¿    IEND®B`‚
------------------------------23473c7acabb--

通过申请可以在接下来的方式创建改装适配器:

With retrofit adapter this request can be created in a next way:

@Multipart
@POST("/api/v1/articles/")
Observable<Response> uploadFile(@Part("author") TypedString authorString,
                                @Part("photo") TypedFile photoFile);

用法:

TypedString author = new TypedString("cURL");
File photoFile = new File("/home/user/Desktop/article-photo.png");
TypedFile photoTypedFile = new TypedFile("image/*", photoFile);
retrofitAdapter.uploadFile(author, photoTypedFile)
               .subscribe(<...>);

它创建类似的输出:

Which creates similar output:

POST http://localhost:8000/api/v1/articles/ HTTP/1.1
Content-Type: multipart/form-data; boundary=32230279-83af-4480-abfc-88a880b21b19
Content-Length: 709
Host: localhost
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/2.3.0

--32230279-83af-4480-abfc-88a880b21b19
Content-Disposition: form-data; name="author"
Content-Type: text/plain; charset=UTF-8
Content-Length: 4
Content-Transfer-Encoding: binary

cUrl
--32230279-83af-4480-abfc-88a880b21b19
Content-Disposition: form-data; name="photo"; filename="article-photo.png"
Content-Type: image/*
Content-Length: 254
Content-Transfer-Encoding: binary

<!RAW BYTES HERE!>

--32230279-83af-4480-abfc-88a880b21b19--

这里的关键区别是,你使用POJO 第三条为多部分参数,默认情况下是由转换器转换成JSON。而你的服务器预计普通字符串代替。随着袅袅您发送卷曲,不是 {作者:卷曲}

The key difference here is that you used POJO Article article as multipart param, which by default is converted by Converter into json. And your server expects plain string instead. With curl you are sending cURL, not {"author":"cURL"}.