我正在尝试使用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());
}
});
我已经尝试了 Call 和 Call,但似乎都不起作用。
服务器端代码在正确设置头和MIME类型后,将文件的字节写入 HttpServletResponse 的输出流中。
我做错了什么?
最后,上传的代码:
@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
对于任何感兴趣的人,上传和下载现在都可以正常工作:以下是解决方案:
服务:
@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());
}
});
restAdapter.setLogLevel(LogLevel.FULL);
。 - Eoin