web-dev-qa-db-fra.com

Téléchargez un fichier binaire avec retrofit 2 dans Android

Je souhaite télécharger un fichier binaire sur le serveur sous Android. Je teste la méthode Api par facteur:

enter image description here

Et c'est OK, comme vous le voyez, il existe une autre option que vous pouvez télécharger des fichiers en tant que données de formulaire (clé, valeur):

enter image description here

Tous les tutoriels (comme celui-ci ) décrivent comment télécharger des fichiers en tant que multipart/form-data:

 // create RequestBody instance from file
    RequestBody requestFile =
            RequestBody.create(MediaType.parse("multipart/form-data"), file);

    // MultipartBody.Part is used to send also the actual file name
    MultipartBody.Part body =
            MultipartBody.Part.createFormData("picture", file.getName(), requestFile);

Je recherche beaucoup mais je n'ai pas trouvé de moyen de télécharger un fichier binaire avec retrofit2.

Il n'y a qu'un seul problème dans le dépôt de mise à niveau qui demande Comment puis-je POST une image binaire en retrofit 2.0 beta?. J'utilise sa solution:

Service API:

@POST("trip/{tripId}/media/photos")
Call<MediaPost> postEventPhoto(
    @Path("eventId") int tripId,
    @Header("Authorization") String accessToken,
    @Query("direction") String direction,
    @Body RequestBody photo);

Votre interlocuteur:

InputStream in = new FileInputStream(new File(media.getPath()));
byte[] buf;
buf = new byte[in.available()];
while (in.read(buf) != -1);
RequestBody requestBody = RequestBody
    .create(MediaType.parse("application/octet-stream"), buf);
Call<MediaPost> mediaPostCall = tripApiService.postTripPhoto(
    tripId,
    ((GlobalInfo) getApplicationContext()).getApiAccessToken(),
    direction,
    requestBody);

Mais j'ai eu cette erreur:

Java.lang.IllegalArgumentException: @Body parameters cannot be used with form or multi-part encoding. 

Qu'est ce qui ne va pas avec mon code? que devrais-je faire?

17
Hamed Ghadirian

Après des heures de recherche, j'ai trouvé qu'il y avait un @Multipart l'annotation reste dans l'interface API de mon code du dernier exemple! ce qui empêche d'envoyer des données binaires au serveur et la solution dans le référentiel de mise à niveau était OK!

4
Hamed Ghadirian

J'ajoute juste une autre solution, car j'ai dû creuser un peu pour comprendre ce qui s'est passé dans la question en premier lieu.

Ma solution est d'obtenir le fichier binaire sous la forme d'un byte[] directement, puis placez-le dans le RequestBody. Donc à la fin, le code ressemblerait à ceci:

interface RetrofitService {
    @POST("api/v1/upload_file")
    Call<Void> uploadBinaryFile(@Body RequestBody body);
}

Et pour l'appeler:

public void uploadBinaryFile(File fileToUpload) {
    retrofitService
        .uploadBinaryFile(RequestBody.create(MediaType.parse("application/octet"), 
            Files.readAllBytes(fileToUpload));
}

C'est fondamentalement la même que la question originale de OP, mais juste pour des raisons de clarté, je laisserai cette réponse également au prochain lecteur.

5
Darwind

J'ai eu le même problème, je voulais télécharger un fichier binaire (image). L'API était de Wordpress

J'ai suivi le code de la solution qui est donné à la fin de ce problème

Voici mon petit code modifié

@POST("wp-json/wp/v2/media/")
Call<ImagePostResult> postEventPhoto(
        @Header("Authorization") String accessToken,
        @Header("Content-Type") String contentType,
        @Header("Content-Disposition") String contentDisposition,
        @Body RequestBody photo);

Voici la demande

        // For BasicAuth
        String authHeader = getAuthHeader();

        String contentType = "application/binary";
        String contentDisposition = "attachment; filename =  " + fileName;

        RequestBody requestBodyee = null;
        try {
            InputStream in = new FileInputStream(file);

            byte[] buf;
            buf = new byte[in.available()];
            while (in.read(buf) != -1) ;
            requestBodyee = RequestBody
                    .create(MediaType.parse("application/octet-stream"), buf);
        } catch (IOException e) {
            e.printStackTrace();
        }


        Call<ImagePostResult> imagePostResultCall = apiInterface.postEventPhoto(
                authHeader,
                contentType,
                contentDisposition,
                requestBodyee);
        imagePostResultCall.enqueue(new Callback<ImagePostResult>() {
            @Override
            public void onResponse(Call<ImagePostResult> call, Response<ImagePostResult> response) {
                // Response Success
                if (response.isSuccessful()) {
                  // yaay
                }
            }

            @Override
            public void onFailure(Call<ImagePostResult> call, Throwable t) {
                Log.d(TAG, "onFailure: " + t);
            }
        });
1
Makarand

juste MediaType == Null mon code:

  private fun put(uploadUrl : String , localPath : String) {
        val file = File(localPath)
        val byteArray = file2Byte(localPath)!!
        val responseBody = RequestBody.create(null , byteArray)
        val call = HttpFactory.providerUp.up(uploadUrl , responseBody)

        call.enqueue(object : Callback<ResponseBody> {
            override fun onFailure(call : retrofit2.Call<ResponseBody>? , t : Throwable?) {
                LogUtil.toast("Failure")
            }

            override fun onResponse(call : retrofit2.Call<ResponseBody>? , response : retrofit.Response<ResponseBody>?) {
                if (response!!.code() == 200) {
                    LogUtil.toast("YES")
                } else {
                    LogUtil.toast("NO")
                }
            }
        })
    }
@PUT
    fun up2(@Url url : String ,@Body requestBody : RequestBody ) : Call<ResponseBody>
0
朱小药

Vous pouvez également envoyer l'image en

//Api Interface

@Part MultipartBody.Part body


//Call in activity
     file = FileUtils.getFile(this, uri);
                            reqFile = RequestBody.create(MediaType.parse("image/*"), file);
                            body = MultipartBody.Part.createFormData("uploaded_file", "Img_" + "_" + rightNow.getTimeInMillis() + ".jpg", reqFile);
0
Rajat Kalia