128 votes

Envoi de fichiers par POST avec HttpURLConnection

Depuis que les développeurs d'Android recommander pour utiliser le HttpURLConnection Je me demandais si quelqu'un pouvait me donner un bon exemple de la façon d'envoyer un "fichier" bitmap (en fait un flux en mémoire) par POST à un serveur HTTP Apache. Je ne suis pas intéressé par les cookies ou l'authentification ou quoi que ce soit de compliqué, mais je veux juste avoir une implémentation fiable et logique. Tous les exemples que j'ai vus ici ressemblent plus à des "essayons ceci et peut-être que ça marchera".

Pour l'instant, j'ai ce code :

URL url;
HttpURLConnection urlConnection = null;
try {
    url = new URL("http://example.com/server.cgi");

    urlConnection = (HttpURLConnection) url.openConnection();

} catch (Exception e) {
    this.showDialog(getApplicationContext(), e.getMessage());
}
finally {
    if (urlConnection != null)
    {
        urlConnection.disconnect();
    }
}

où showDialog devrait juste afficher un AlertDialog (en cas d'URL invalide ?).

Maintenant, disons que je génère un bitmap comme ceci : Bitmap image = this.getBitmap() à l'intérieur d'un contrôle dérivé de View et je veux l'envoyer par POST. Quelle serait la procédure à suivre pour réaliser une telle chose ? Quelles classes dois-je utiliser ? Puis-je utiliser HttpPost comme dans cet exemple ? Si oui, comment dois-je construire le InputStreamEntity pour mon bitmap ? Je trouverais révoltant de devoir d'abord stocker le bitmap dans un fichier sur l'appareil.


Je dois également mentionner que j'ai vraiment besoin d'envoyer chaque pixel non modifié du bitmap d'origine au serveur, et que je ne peux donc pas le convertir en JPEG.

2voto

m_____ilk Points 59

En se basant sur la solution de Mihai, si quelqu'un a le problème de sauvegarder des images sur le serveur comme ce qui s'est passé sur mon serveur, changez la partie Bitmap to bytebuffer en :

ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG,100,bos);
        byte[] pixels = bos.toByteArray();

1voto

Rico Yao Points 220

Je ne l'ai pas testé, mais vous pouvez essayer d'utiliser PipedInputStream et PipedOutputStream. Cela pourrait ressembler à quelque chose comme :

final Bitmap bmp = … // your bitmap

// Set up Piped streams
final PipedOutputStream pos = new PipedOutputStream(new ByteArrayOutputStream());
final PipedInputStream pis = new PipedInputStream(pos);

// Send bitmap data to the PipedOutputStream in a separate thread
new Thread() {
    public void run() {
        bmp.compress(Bitmap.CompressFormat.PNG, 100, pos);
    }
}.start();

// Send POST request
try {
    // Construct InputStreamEntity that feeds off of the PipedInputStream
    InputStreamEntity reqEntity = new InputStreamEntity(pis, -1);

    HttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost(url);
    reqEntity.setContentType("binary/octet-stream");
    reqEntity.setChunked(true);
    httppost.setEntity(reqEntity);
    HttpResponse response = httpclient.execute(httppost);
} catch (Exception e) {
    e.printStackTrace()
}

0voto

Voici ce que j'ai fait pour télécharger une photo en utilisant la requête post.

public void uploadFile(int directoryID, String filePath) {
    Bitmap bitmapOrg = BitmapFactory.decodeFile(filePath);
    ByteArrayOutputStream bao = new ByteArrayOutputStream();

    String upload_url = BASE_URL + UPLOAD_FILE;
    bitmapOrg.compress(Bitmap.CompressFormat.JPEG, 90, bao);

    byte[] data = bao.toByteArray();

    HttpClient httpClient = new DefaultHttpClient();
    HttpPost postRequest = new HttpPost(upload_url);
    MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);

    try {
        // Set Data and Content-type header for the image
        FileBody fb = new FileBody(new File(filePath), "image/jpeg");
        StringBody contentString = new StringBody(directoryID + "");

        entity.addPart("file", fb);
        entity.addPart("directory_id", contentString);
        postRequest.setEntity(entity);

        HttpResponse response = httpClient.execute(postRequest);
        // Read the response
        String jsonString = EntityUtils.toString(response.getEntity());
        Log.e("response after uploading file ", jsonString);

    } catch (Exception e) {
        Log.e("Error in uploadFile", e.getMessage());
    }
}

NOTE : Ce code nécessite des bibliothèques, alors suivez les instructions aquí afin d'obtenir les bibliothèques.

0voto

Clive Jefferies Points 56

J'ai trouvé l'utilisation d'okHttp beaucoup plus facile, car je n'ai pu faire fonctionner aucune de ces solutions : https://stackoverflow.com/a/37942387/447549

0voto

Viktor Nikitenko Points 134

J'ai essayé les solutions ci-dessus et aucune n'a fonctionné pour moi.

Cependant http://www.baeldung.com/httpclient-post-http-request . Ligne 6 POST Multipart Request a fonctionné en quelques secondes

public void whenSendMultipartRequestUsingHttpClient_thenCorrect() 
  throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();
    HttpPost httpPost = new HttpPost("http://www.example.com");

    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addTextBody("username", "John");
    builder.addTextBody("password", "pass");
    builder.addBinaryBody("file", new File("test.txt"),
      ContentType.APPLICATION_OCTET_STREAM, "file.ext");

    HttpEntity multipart = builder.build();
    httpPost.setEntity(multipart);

    CloseableHttpResponse response = client.execute(httpPost);
    client.close();
}

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