partmap files android image-uploading multipartform-data retrofit

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 convertidor RestAdapter o pueden implementar TypedOutput para manejar su propia serialización.

Relacionado


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".