files - upload file android
¿Cómo enviar multipart/form-data con Retrofit? (2)
De acuerdo con tu solicitud de rizo, estás intentando crear algo así:
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--
Con el adaptador de adaptación, esta solicitud se puede crear de la siguiente manera:
@Multipart
@POST("/api/v1/articles/")
Observable<Response> uploadFile(@Part("author") TypedString authorString,
@Part("photo") TypedFile photoFile);
Uso:
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(<...>);
Lo que crea resultados similares:
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--
La diferencia clave aquí es que usó el Article article
POJO como multipart param, que de forma predeterminada es convertido por Converter
al json. Y su servidor espera una cadena simple en su lugar. Con curl estás enviando cURL
, no {"author":"cURL"}
.
Quiero enviar un artículo desde y un cliente de Android a un servidor REST. Aquí está el modelo de Python desde el servidor:
class Article(models.Model):
author = models.CharField(max_length=256, blank=False)
photo = models.ImageField()
La siguiente interfaz describe la implementación anterior:
@POST("/api/v1/articles/")
public Observable<CreateArticleResponse> createArticle(
@Body Article article
);
Ahora quiero enviar una imagen con los datos del artículo . La photo
no es parte del modelo del artículo en el cliente de Android .
@Multipart
@POST("/api/v1/articles/")
public Observable<CreateArticleResponse> createArticle(
@Part("article") Article article,
@Part("photo") TypedFile photo
);
La API está preparada y probada con éxito con 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"
Cuando envío datos a través de createArticle()
desde el cliente de Android , recibo un estado HTTP 400
que indica que los campos son obligatorios / faltan .
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
Esto es lo que se recibe como request.data
en el lado del servidor:
ipdb> print request.data
<QueryDict: {u''article'': [u''{"author":"me"}''], /
u''photo'': [<TemporaryUploadedFile: IMG_1759215522.jpg /
(multipart/form-data)>]}>
¿Cómo se puede convertir el objeto de artículo en un tipo de datos conformado multiparte? Leí que Retrofit podría permitir el uso de Converters para esto. Debería ser algo que implemente un retrofit.mime.TypedOutput
por lo que entendí para la Retrofit .
Las piezas de
RestAdapter
partes utilizan el convertidorRestAdapter
o pueden implementarTypedOutput
para manejar su propia serialización.
Relacionado
- Especificación HTML 4.01 - Envío de formulario - multiparte / formulario-datos
- Retrofit Annotation Type Documentación de pieza
- ¿Cargar datos de imagen multiparte en JSON con Retrofit?
- REST - HTTP Post Multipart con JSON
- La imagen de carga multiparte de actualización falló
- Problema de modificación # 178: Crear manual para enviar archivos con actualización
- Problema de actualización # 531: Problema al cargar el archivo a través de POST / Multipart
- Problema de modificación n. ° 658: no se pueden enviar los parámetros de cadena con la imagen cuando se usa Multipart
- Problema de modificación # 662: Formulario de modificación codificado y multiparte en una sola solicitud
El servidor espera una cadena de "autor", pero está intentando pasarle un objeto de "artículo". Pásalo "Autor de cadena" en lugar de "Artículo artículo".
Además, creo que el error "no hay archivo enviado" es una pista falsa porque el archivo está claramente presente en su "request.data".