gpt4 book ai didi

android - 如何使用 Retrofit 发送多部分/表单数据?

转载 作者:IT老高 更新时间:2023-10-28 21:56:11 26 4
gpt4 key购买 nike

我想从 Android 客户端向 REST 服务器发送 Article。这是来自服务器的 Python 模型:

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

下面的接口(interface)描述了之前的实现:

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

现在我想发送带有 Article 数据的图像。 photo 不是 Android 客户端上 Article 模型的一部分。

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

API 已准备好并已使用 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 状态,指出 字段是必需/缺失

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 接收的内容:

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

如何将 Article 对象转换为多部分一致性数据类型?我读到 Retrofit可能允许使用 Converters为了这。据我对 documentation 的理解,它应该是实现 retrofit.mime.TypedOutput 的东西。 .

Multipart parts use the RestAdapter's converter or they can implement TypedOutput to handle their own serialization.

相关

最佳答案

根据您的 curl 请求,您正尝试像这样创建 smth:

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!>

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

使用改造适配器可以通过以下方式创建此请求:

@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 作为多部分参数,默认情况下由 Converter 转换为 json。而您的服务器则需要纯字符串。使用 curl 您发送的是 cURL,而不是 {"author":"cURL"}

关于android - 如何使用 Retrofit 发送多部分/表单数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29680158/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com