改造2文件下载/上传

我正在尝试使用retrofit 2下载/上传文件,但找不到任何有关如何操作的教程示例。 我的下载代码是:

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

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

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

服务器端代码在正确设置标题和MIMEtypes后,将文件的字节写入HttpServletResponse的输出stream。

我究竟做错了什么?

最后,上传代码:

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

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

谢谢!

编辑:

答案后,下载只会产生一个损坏的文件(没有@Streaming),上传不会。 当我使用上面的代码时,服务器返回一个400错误。 将其更改为

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

,请求执行但后端似乎不接收文件。

后端代码:

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

我究竟做错了什么? 我能够通过Apache HttpClient使用普通Java的后端:

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

编辑v2

对于任何感兴趣的人,现在都可以上传和下载:这些解决scheme是:

服务:

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

下载代码:

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

上传代码:

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

Solutions Collecting From Web of "改造2文件下载/上传"

对于下载,您可以使用ResponseBody作为您的返回types –

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

您可以在回拨中获得ResponseBodyinputstream –

 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 

如果您的服务器正确处理多部分邮件,您的上传看起来一目了然。 它工作吗? 如果不是,你能解释失败模式吗? 您也可以通过不使其成为多部分来简化。 删除@Multipart注释并将@Path转换为@Body

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

我正在使用retrofit 2.0.0-beta2,并通过使用multipart请求上传图像时遇到问题。 我解决了这个问题: https : //stackoverflow.com/a/32796626/2915075

对我来说关键是使用标准的POST和MultipartRequestBody来代替@Multipart注释的请求。

这是我的代码:

改造服务类

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

从活动中使用,片段:

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

我有同样的问题,我find了上传文件的解决scheme,这里描述当通过改造2上传图片时是否可以显示进度条

此外,我有这个问题,这是我如何尝试解决我的问题(修改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)); ?> 

您可以使用Retrofit 2.0参考Image Download的教程

目前您可以参考以下图片下载function:

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

以下是使用Retrofit 2.0的文件处理零件图像下载

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

我希望这会有所帮助。 祝一切顺利。 快乐编码:)