改造2文件下/上传 [英] Retrofit 2 file down/upload

查看:304
本文介绍了改造2文件下/上传的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想下/上载与改造2一个文件,但无法找到如何做到这一点任何教程的例子。 我的code为下载是:

  @GET(文件/结账)
公共呼叫<文件>结帐(@Query(值=documentUrl)字符串documentUrl,@Query(值=accessToken)字符串accessToken,@Query(值=表示只读)布尔只读);
 

 呼叫<文件>调用= RetrofitSingleton.getInstance(serverAddress)
                .checkout(document.getContentUrl(),apiToken,只读[I]);
call.enqueue(新回拨<文件>(){
        @覆盖
        公共无效onResponse(响应<文件>的响应,
                改造改造){
            字符串文件名= document.getFileName();
            尝试 {
                的System.out.println(response.body());
                。长文件长度= response.body()长度();
                输入的InputStream =新的FileInputStream(response.body());
                文件路径= Environment.getExternalStorageDirectory();
                档案文件=新的文件(路径,文件名);
                的BufferedOutputStream输出=新的BufferedOutputStream(
                        新的FileOutputStream(文件));
                字节的数据[] =新的字节[1024];

                总长= 0;
                诠释计数;
                而((计数= input.read(数据))!=  -  1){
                    共有+ =计数;
                    output.write(数据,0,计数);
                }

                output.flush();

                output.close();
            }赶上(IOException异常E){
                字符串logTag =TempTag还可;
                Log.e(logTag,错误而写的文件!);
                Log.e(logTag,e.toString());
            }
        }
        @覆盖
        公共无效onFailure(的Throwable T){
            // TODO:错误处理
            的System.out.println(t.toString());
        }
    });
 

我试着呼叫和呼叫,但似乎没有任何工作。

服务器端code正确设置标题和MIME类型之后写入文件的字节到HttpServletResponse的输出流。

我是什么做错了吗?

最后,上传code:

  @Multipart
@POST(文件/签)
公共呼叫<字符串>签(@Query(值=documentId)字符串documentId,@Query(值=name)的字符串文件名,@Query(值=accessToken)字符串accessToken,@Part(文件)RequestBody文件);
 

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

            呼叫<字符串>调用= RetrofitSingleton.getInstance(serverAddress).checkin(documentId,document.getFileName(),apiToken,requestBody);
            call.enqueue(新回拨<字符串>(){
                @覆盖
                公共无效onResponse(响应<字符串>响应,改造改造){
                    的System.out.println(response.body());
                }

                @覆盖
                公共无效onFailure(的Throwable T){
                    的System.out.println(t.toString());
                }
            });
 

谢谢!

编辑:

答案后,仅下载产生损坏的文件(不@Streaming),上传不和。当我使用上述code,服务器会返回400错误。将其更改为后

  RequestBody requestBody = RequestBody.create(MediaType.parse(document.getMimeType()),文件);
            MultipartBuilder multipartBuilder =新MultipartBuilder();
            multipartBuilder.addFormDataPart(文件,document.getFileName(),requestBody);

            呼叫<字符串>调用= RetrofitSingleton.getInstance(serverAddress).checkin(documentId,document.getFileName(),apiToken,multipartBuilder.build());
 

,请求执行但后端似乎没有接收文件

后端code:

  @RequestMapping(值=/文档/签入,方法= RequestMethod.POST)
公共无效checkInDocument(@RequestParam字符串documentId,
        @RequestParam字符串名称,@RequestParam MultipartFile文件,
        @RequestParam字符串accessToken,HttpServletResponse的响应)
 

我是什么做错了吗?我能够使用后端从普通的Java与Apache HttpClient的:

  MultipartEntityBuilder建设者= MultipartEntityBuilder.create();
    builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    builder.addBinaryBody(文件,新的文件(E:\\ \\温度test.jpg放在));
    HttpEntity httpEntity = builder.build();
    的System.out.println(HttpEntity+ EntityUtils.toString(httpEntity));
    HttpPost httpPost =新HttpPost(URI);
    httpPost.setEntity(httpEntity);
 

修改V2

有关兴趣的人,无论是上传和下载现在的工作:这是解决方案:

服务:

  @GET(文件/结账)
公共呼叫< ResponseBody>结帐(@Query(值=documentUrl)字符串documentUrl,@Query(值=accessToken)字符串accessToken,@Query(值=表示只读)布尔只读);

@Multipart
@POST(文件/签)
公共呼叫<字符串>签(@Query(值=documentId)字符串documentId,@Query(值=name)的字符串文件名,@Query(值=accessToken)字符串accessToken,@Part(文件)RequestBody文件);
 

下载code:

 呼叫< ResponseBody>调用= RetrofitSingleton.getInstance(serverAddress)
                .checkout(document.getContentUrl(),apiToken,只读[I]);
        call.enqueue(新回拨< ResponseBody>(){
            @覆盖
            公共无效onResponse(响应< ResponseBody>响应,
                    改造改造){
                字符串文件名= document.getFileName();

                尝试 {
                    文件路径= Environment.getExternalStorageDirectory();
                    档案文件=新的文件(路径,文件名);
                    FileOutputStream中的FileOutputStream =新的FileOutputStream(文件);
                    IOUtils.write(response.body()字节(),FileOutputStream中。);
                }赶上(IOException异常E){
                    Log.e(logTag,错误而写的文件!);
                    Log.e(logTag,e.toString());
                }
            }

            @覆盖
            公共无效onFailure(的Throwable T){
                // TODO:错误处理
                的System.out.println(t.toString());
            }
        });
 

上传code:

 呼叫<字符串>调用= RetrofitSingleton
                    .getInstance(serverAddress).checkin(documentId,
                            document.getFileName(),apiToken,
                            multipartBuilder.build());
            call.enqueue(新回拨<字符串>(){
                @覆盖
                公共无效onResponse(响应<字符串>响应,
                        改造改造){
                    这里//处理响应
                }

                @覆盖
                公共无效onFailure(的Throwable T){
                    // TODO:错误处理
                    的System.out.println(错误);
                    的System.out.println(t.toString());
                }
            });
 

解决方案

有关下载,你可以使用 ResponseBody 为您的返回类型 -

  @GET(文件/结账)
@Streaming
公共呼叫< ResponseBoy>结帐(@Query(值=documentUrl)字符串documentUrl,@Query(值=accessToken)字符串accessToken,@Query(值=表示只读)布尔只读);
 

和你可以在你的回调 ResponseBody 输入流 -

 呼叫< ResponseBody>调用= RetrofitSingleton.getInstance(serverAddress)
            .checkout(document.getContentUrl(),apiToken,只读[I]);

call.enqueue(新回拨< ResponseBody>(){
        @覆盖
        公共无效onResponse(响应< ResponseBody>响应,
                改造改造){
            字符串文件名= document.getFileName();
            尝试 {
                InputStream中输入= response.body()的字节流()。
                //你的code休息
 

您上传看起来不错的第一眼,如果你的服务器正确处理多部分消息。难道它的工作?如果没有,你能解释的故障模式?您还可能能够通过不使它多部分简化。删除 @Multipart 诠释和转换 @Path @Body -

  @POST(文件/签)
公共呼叫<字符串>签(@Query(值=documentId)字符串documentId,@Query(值=name)的字符串文件名,@Query(值=accessToken)字符串accessToken,@Body RequestBody文件);
 

I'm trying to down/upload a file with retrofit 2 but can't find any tutorials examples on how to do so. My code for downloading is:

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

and

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());
        }
    });

I've tried with Call and Call but nothing seems to work.

The server-side code writes the file's bytes into HttpServletResponse's output stream after setting the headers and mime type correctly.

What am I doing wrong?

Finally, the 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);

and

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());
                }
            });

Thanks!

Edit:

After the answer, downloading only yields a corrupted file (without the @Streaming), uploading doesn't as well. When I use the above code, the server returns a 400 error. After changing it to

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());

, the request executes but the backend doesn't seem to receive a file.

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)

What am I doing wrong? I was able to use the backend from plain Java with the Apache HttpClient:

    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

For anyone interested, both up- and downloading work now: These are the solutions:

Service:

@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);

Download Code:

    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());
                }
            });

解决方案

For downloading, you can use ResponseBody as your return type --

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

and you can get the ResponseBody input stream in your call back --

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

Your upload looks okay at first glance if you server handles multipart messages correctly. Is it working? If not, can you explain the failure mode? You also might be able to simplify by not making it multipart. Remove the @Multipart annotation and convert @Path to @Body --

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

这篇关于改造2文件下/上传的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆