webentwicklung-frage-antwort-db.com.de

Retrofit 2 Datei runter / hochladen

Ich versuche, eine Datei mit Retrofit 2 herunterzuladen/hochzuladen, kann jedoch keine Beispiele für Anleitungen dazu finden. Mein Code zum Herunterladen ist:

@GET("documents/checkout")
public Call<File> checkout(@Query(value = "documentUrl") String documentUrl, @Query(value = "accessToken") String accessToken, @Query(value = "readOnly") boolean readOnly);

und

Call<File> call = RetrofitSingleton.getInstance(serverAddress)
                .checkout(document.getContentUrl(), apiToken, readOnly[i]);
call.enqueue(new Callback<File>() {
        @Override
        public void onResponse(Response<File> response,
                Retrofit retrofit) {
            String fileName = document.getFileName();
            try {
                System.out.println(response.body());
                long fileLength = response.body().length();
                InputStream input = new FileInputStream(response.body());
                File path = Environment.getExternalStorageDirectory();
                File file = new File(path, fileName);
                BufferedOutputStream output = new BufferedOutputStream(
                        new FileOutputStream(file));
                byte data[] = new byte[1024];

                long total = 0;
                int count;
                while ((count = input.read(data)) != -1) {
                    total += count;
                    output.write(data, 0, count);
                }

                output.flush();

                output.close();
            } catch (IOException e) {
                String logTag = "TEMPTAG";
                Log.e(logTag, "Error while writing file!");
                Log.e(logTag, e.toString());
            }
        }
        @Override
        public void onFailure(Throwable t) {
            // TODO: Error handling
            System.out.println(t.toString());
        }
    });

Ich habe es mit Call and Call versucht, aber nichts scheint zu funktionieren.

Der serverseitige Code schreibt die Bytes der Datei in den Ausgabestream von HttpServletResponse, nachdem die Header und der MIME-Typ korrekt festgelegt wurden.

Was mache ich falsch?

Zum Schluss der Upload-Code:

@Multipart
@POST("documents/checkin")
public Call<String> checkin(@Query(value = "documentId") String documentId, @Query(value = "name") String fileName, @Query(value = "accessToken") String accessToken, @Part("file") RequestBody file);

und

RequestBody requestBody = RequestBody.create(MediaType.parse(document.getMimeType()), file);

            Call<String> call = RetrofitSingleton.getInstance(serverAddress).checkin(documentId, document.getFileName(), apiToken, requestBody);
            call.enqueue(new Callback<String>() {
                @Override
                public void onResponse(Response<String> response, Retrofit retrofit) {
                    System.out.println(response.body());
                }

                @Override
                public void onFailure(Throwable t) {
                    System.out.println(t.toString());
                }
            });

Vielen Dank!

Bearbeiten:

Nach der Antwort führt das Herunterladen nur zu einer beschädigten Datei (ohne @Streaming), das Hochladen funktioniert nicht so gut. Wenn ich den obigen Code verwende, gibt der Server einen 400-Fehler zurück. Nach dem Ändern auf

RequestBody requestBody = RequestBody.create(MediaType.parse(document.getMimeType()), file);
            MultipartBuilder multipartBuilder = new MultipartBuilder();
            multipartBuilder.addFormDataPart("file", document.getFileName(), requestBody);

            Call<String> call = RetrofitSingleton.getInstance(serverAddress).checkin(documentId, document.getFileName(), apiToken, multipartBuilder.build());

wird die Anfrage ausgeführt, aber das Backend scheint keine Datei zu erhalten.

Backend-Code:

@RequestMapping(value = "/documents/checkin", method = RequestMethod.POST)
public void checkInDocument(@RequestParam String documentId,
        @RequestParam String name, @RequestParam MultipartFile file,
        @RequestParam String accessToken, HttpServletResponse response)

Was mache ich falsch? Ich konnte das Backend von plain Java mit dem Apache HttpClient benutzen:

    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    builder.addBinaryBody("file", new File("E:\\temp\\test.jpg"));
    HttpEntity httpEntity = builder.build();
    System.out.println("HttpEntity " + EntityUtils.toString(httpEntity.));
    HttpPost httpPost = new HttpPost(uri);
    httpPost.setEntity(httpEntity);

Edit v2

Für alle Interessierten funktioniert das Up- und Downloaden jetzt: Dies sind die Lösungen:

Bedienung:

@GET("documents/checkout")
public Call<ResponseBody> checkout(@Query(value = "documentUrl") String documentUrl, @Query(value = "accessToken") String accessToken, @Query(value = "readOnly") boolean readOnly);

@Multipart
@POST("documents/checkin")
public Call<String> checkin(@Query(value = "documentId") String documentId, @Query(value = "name") String fileName, @Query(value = "accessToken") String accessToken, @Part("file") RequestBody file);

Code herunterladen:

    Call<ResponseBody> call = RetrofitSingleton.getInstance(serverAddress)
                .checkout(document.getContentUrl(), apiToken, readOnly[i]);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Response<ResponseBody> response,
                    Retrofit retrofit) {
                String fileName = document.getFileName();

                try {
                    File path = Environment.getExternalStorageDirectory();
                    File file = new File(path, fileName);
                    FileOutputStream fileOutputStream = new FileOutputStream(file);
                    IOUtils.write(response.body().bytes(), fileOutputStream);
                } catch (IOException e) {
                    Log.e(logTag, "Error while writing file!");
                    Log.e(logTag, e.toString());
                }
            }

            @Override
            public void onFailure(Throwable t) {
                // TODO: Error handling
                System.out.println(t.toString());
            }
        });

Upload-Code:

    Call<String> call = RetrofitSingleton
                    .getInstance(serverAddress).checkin(documentId,
                            document.getFileName(), apiToken,
                            multipartBuilder.build());
            call.enqueue(new Callback<String>() {
                @Override
                public void onResponse(Response<String> response,
                        Retrofit retrofit) {
                    // Handle response here
                }

                @Override
                public void onFailure(Throwable t) {
                    // TODO: Error handling
                    System.out.println("Error");
                    System.out.println(t.toString());
                }
            });
28
N4zroth

Zum Herunterladen können Sie ResponseBody als Rückgabetyp verwenden -

@GET("documents/checkout")
@Streaming
public Call<ResponseBody> checkout(@Query("documentUrl") String documentUrl, @Query("accessToken") String accessToken, @Query("readOnly") boolean readOnly);

und Sie können den Eingabestream ResponseBody in Ihrem Rückruf erhalten -

Call<ResponseBody> call = RetrofitSingleton.getInstance(serverAddress)
            .checkout(document.getContentUrl(), apiToken, readOnly[i]);

call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Response<ResponseBody> response,
                Retrofit retrofit) {
            String fileName = document.getFileName();
            try {
                InputStream input = response.body().byteStream();
                //  rest of your code

Ihr Upload sieht auf den ersten Blick in Ordnung aus, wenn Ihr Server mehrteilige Nachrichten korrekt verarbeitet. Funktioniert es? Wenn nicht, können Sie den Fehlermodus erklären? Möglicherweise können Sie auch vereinfachen, indem Sie es nicht mehrteilig machen. Entferne das @Multipart Annotation und Konvertierung @Path bis @Body -

@POST("documents/checkin")
public Call<String> checkin(@Query("documentId") String documentId, @Query("name") String fileName, @Query("accessToken") String accessToken, @Body RequestBody file);
21
iagreen

Ich verwende Retrofit 2.0.0-Beta2 und es gab ein Problem beim Hochladen von Bildern mithilfe einer mehrteiligen Anforderung. Ich habe es mit dieser Antwort gelöst: https://stackoverflow.com/a/32796626/2915075

Der Schlüssel für mich war, standard POST with MultipartRequestBody anstelle von @Multipart annotated request zu verwenden.

Hier ist mein Code:

Serviceklasse nachrüsten

@POST("photo")
Call<JsonElement> uploadPhoto(@Body RequestBody imageFile, @Query("sessionId"));

Verwendung von Aktivität, Fragment:

RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpeg"), imageFile);
MultipartBuilder multipartBuilder = new MultipartBuilder();
multipartBuilder.addFormDataPart("photo", imageFile.getName(), fileBody);
RequestBody fileRequestBody = multipartBuilder.build();

//call
mRestClient.getRetrofitService().uploadProfilePhoto(fileRequestBody, sessionId);

ich habe die gleichen Probleme und eine Lösung zum Hochladen von Dateien gefunden, die hier beschrieben wird Ist es möglich, den Fortschrittsbalken beim Hochladen von Bildern über Retrofit 2 anzuzeigen

1

Auch ich hatte dieses Problem, So versuche ich mein Problem zu lösen (RETROFIT 2)

 //1. What We Need From Server ( upload.php Script )
    public class FromServer {
        String result;
    }

    //2. Which Interface To Communicate Our upload.php Script?
    public interface ServerAPI {

        @Multipart
        @POST("upload.php")//Our Destination PHP Script
        Call<List<FromServer>> upload(
                @Part("file_name") String file_name,
                @Part("file") RequestBody description);

         Retrofit retrofit =
                new Retrofit.Builder()
                        .baseUrl("http://192.168.43.135/retro/") // REMEMBER TO END with /
                        .addConverterFactory(GsonConverterFactory.create())
                 .build();
    }


    //3. How To Upload
    private void upload(){

            ServerAPI api = ServerAPI.retrofit.create(ServerAPI.class);

            File from_phone = FileUtils.getFile(Environment.getExternalStorageDirectory()+"/aa.jpg"); //org.Apache.commons.io.FileUtils
            RequestBody to_server = RequestBody.create(MediaType.parse("multipart/form-data"), from_phone);

            api.upload(from_phone.getName(),to_server).enqueue(new Callback<List<FromServer>>() {
                @Override
                public void onResponse(Call<List<FromServer>> call, Response<List<FromServer>> response) {
                    Toast.makeText(MainActivity.this, response.body().get(0).result, Toast.LENGTH_SHORT).show();
                }
                @Override
                public void onFailure(Call<List<FromServer>> call, Throwable t) { }
            });


         }

//4. upload.php
<?php

    $pic = $_POST['file_name'];

    $pic = str_replace("\"", "", $pic); //REMOVE " from file name
    if(file_exists($pic)){unlink($pic);}

    $f = fopen($pic, "w");
    fwrite($f,$_POST['file']);
    fclose($f);

    $arr[] = array("result"=>"Done");
    print(json_encode($arr));
?>
1
ugali soft

Sie können Tutorial für Image Download mit Retrofit 2.0 beziehen

Für den Download von Bildern stehen Ihnen vorerst folgende Funktionen zur Verfügung:

void getRetrofitImage() {

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(url)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    RetrofitImageAPI service = retrofit.create(RetrofitImageAPI.class);

    Call<ResponseBody> call = service.getImageDetails();

    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {

            try {

                Log.d("onResponse", "Response came from server");

                boolean FileDownloaded = DownloadImage(response.body());

                Log.d("onResponse", "Image is downloaded and saved ? " + FileDownloaded);

            } catch (Exception e) {
                Log.d("onResponse", "There is an error");
                e.printStackTrace();
            }

        }

        @Override
        public void onFailure(Throwable t) {
            Log.d("onFailure", t.toString());
        }
    });
}

Im Folgenden wird das Herunterladen von Teilbildern zur Dateiverwaltung mit Retrofit 2.0 beschrieben

private boolean DownloadImage(ResponseBody body) {

    try {
        Log.d("DownloadImage", "Reading and writing file");
        InputStream in = null;
        FileOutputStream out = null;

        try {
            in = body.byteStream();
            out = new FileOutputStream(getExternalFilesDir(null) + File.separator + "AndroidTutorialPoint.jpg");
            int c;

            while ((c = in.read()) != -1) {
                out.write(c);
            }
        }
        catch (IOException e) {
            Log.d("DownloadImage",e.toString());
            return false;
        }
        finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }

        int width, height;
        ImageView image = (ImageView) findViewById(R.id.imageViewId);
        Bitmap bMap = BitmapFactory.decodeFile(getExternalFilesDir(null) + File.separator + "AndroidTutorialPoint.jpg");
        width = 2*bMap.getWidth();
        height = 6*bMap.getHeight();
        Bitmap bMap2 = Bitmap.createScaledBitmap(bMap, width, height, false);
        image.setImageBitmap(bMap2);

        return true;

    } catch (IOException e) {
        Log.d("DownloadImage",e.toString());
        return false;
    }
}

Ich hoffe es wird helfen. Alles Gute. Happy Coding :)

0
Navneet Goel