87 votes

Comment envoyer un POST «multipart / form-data» sous Android avec Volley

Quelqu'un a pu accomplir cela? Je n'ai pas eu de succès en essayant de télécharger une image/png à l'aide d'une requête POST à notre serveur, et je suis curieux de savoir si quelqu'un a de. Je crois que la méthode par défaut pour ce faire serait de remplacer public byte[] getPostBody()dans le Request.java classe et joindre le Fichier, avec un en-Tête vide clés de la frontière. Toutefois, la conversion de mon fichier dans une Chaîne de caractères pour l' Map<String, String> postParams et de l'avoir codé semble de nouveau obtus et très pas très élégant (également échoué dans mes tentatives). C'est vraiment la seule chose qui nous retient de passer à cette bibliothèque.

De toute façon, toutes les pensées et les réponses sont très appréciés. Je vous remercie pour votre aide.

73voto

alex Points 1310

J'ai peut-être tort sur ce sujet, mais je pense que vous devez mettre en place votre propre com.android.le volley.boîte à outils.HttpStack pour cela, car la valeur par défaut (HurlStack si la version > pain d'épice ou HttpClientStack) ne pas traiter avec des " multipart/form-data.

Edit:

Et en effet je me suis trompé. J'ai été en mesure de le faire à l'aide de MultipartEntity dans la Requête comme ceci:

public class MultipartRequest extends Request<String> {

    private MultipartEntity entity = new MultipartEntity();

    private static final String FILE_PART_NAME = "file";
    private static final String STRING_PART_NAME = "text";

    private final Response.Listener<String> mListener;
    private final File mFilePart;
    private final String mStringPart;

    public MultipartRequest(String url, Response.ErrorListener errorListener, Response.Listener<String> listener, File file, String stringPart)
    {
        super(Method.POST, url, errorListener);

        mListener = listener;
        mFilePart = file;
        mStringPart = stringPart;
        buildMultipartEntity();
    }

    private void buildMultipartEntity()
    {
        entity.addPart(FILE_PART_NAME, new FileBody(mFilePart));
        try
        {
            entity.addPart(STRING_PART_NAME, new StringBody(mStringPart));
        }
        catch (UnsupportedEncodingException e)
        {
            VolleyLog.e("UnsupportedEncodingException");
        }
    }

    @Override
    public String getBodyContentType()
    {
        return entity.getContentType().getValue();
    }

    @Override
    public byte[] getBody() throws AuthFailureError
    {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try
        {
            entity.writeTo(bos);
        }
        catch (IOException e)
        {
            VolleyLog.e("IOException writing to ByteArrayOutputStream");
        }
        return bos.toByteArray();
    }

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response)
    {
        return Response.success("Uploaded", getCacheEntry());
    }

    @Override
    protected void deliverResponse(String response)
    {
        mListener.onResponse(response);
    }
}

C'est assez cru, mais je l'ai essayé avec une image et une chaîne simple et ça fonctionne. La réponse est un espace réservé, ne pas faire beaucoup de sens pour retourner une Chaîne de Réponse dans ce cas. J'ai eu des problèmes à l'aide d'apache httpmime à utiliser MultipartEntity j'ai donc utilisé cette https://code.google.com/p/httpclientandroidlib/ ne sais pas si il ya une meilleure façon. Espérons que cela aide.

Modifier

Vous pouvez utiliser httpmime sans l'aide de httpclientandroidlib, la seule dépendance est httpcore.

13voto

Ogre_BGR Points 4799

Comme mentionné dans la présentation de l'I/O (4:05), Volley-ball "est terrible" pour les grandes charges utiles. Comme je comprends ce que cela signifie de ne pas utiliser de Volley pour la réception/l'envoi de (gros) fichiers. En regardant le code, il semble qu'il n'est même pas conçu pour gérer plusieurs parties de données de formulaire (par ex. Request.java a getBodyContentType() avec codé en dur "application/x-www-form-urlencoded"; HttpClientStack::createHttpRequest() peut gérer qu'un seul byte[], etc...). Vous serez sans doute en mesure de créer de mise en œuvre qui peut gérer plusieurs parties, mais Si j'étais vous, je vais juste utiliser HttpClient directement avec MultipartEntity comme:

    HttpPost req = new HttpPost(composeTargetUrl());
    MultipartEntity entity = new MultipartEntity();
    entity.addPart(POST_IMAGE_VAR_NAME, new FileBody(toUpload));
    try {
        entity.addPart(POST_SESSION_VAR_NAME, new StringBody(uploadSessionId));
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException(e);
    }
    req.setEntity(entity);

Vous pouvez avoir besoin plus récente HttpClient (c'est à dire pas intégrés), ou mieux encore, l'utilisation de Volley avec les nouveaux HttpClient

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X