如何使用 Retrofit 发送多部分/表单数据? [英] How to send multipart/form-data with Retrofit?
问题描述
我想从 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
);
现在我想发送带有文章数据的图像.照片
不是 Android 客户端上的 文章 模型的一部分.
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 已准备好并通过 cURL 成功测试.
The API is prepared and successfully tested with cURL.
$ 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"
当我从 Android 客户端通过 createArticle()
发送数据时,我收到一个 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)>]}>
如何将Article 对象转换为多部分符合数据类型?我读到 Retrofit 可能允许使用 转换器为此.据我了解 文档.
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 implementTypedOutput
to handle their own serialization.
相关
- HTML 4.01 规范 - 表单提交 - multipart/form-数据
- 改造注解类型部分文档
- 使用 Retrofit 以 JSON 格式上传多部分图像数据?一个>
- REST - HTTP Post Multipart with JSON
- 改造分段上传图片失败
- 改造问题 #178:创建使用改造发送文件的手册
- 改造问题 #531:通过 POST/Multipart 上传文件时出现问题
- 改造问题 #658:使用 Multipart 时无法发送带有图像的字符串参数
- 改造问题 #662:在单个请求中改造表单编码和多部分
推荐答案
根据您的 curl 请求,您正在尝试像这样创建 smth:
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(<...>);
创建类似的输出:
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 Article article
作为 multipart param,默认情况下由 Converter
转换为 json.而您的服务器需要纯字符串.使用 curl,您发送的是 cURL
,而不是 {"author":"cURL"}
.
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"}
.
这篇关于如何使用 Retrofit 发送多部分/表单数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!