使用 Retrofit 2.0 上传多个文件
multiple file upload using retrofit 2.0
我目前正在处理应用程序的一部分,用户需要从图库中选择一些图像,然后将这些图像上传到服务器。对于上传,我使用的是使用 multipart 的改造 2.0。
根据资源 https://futurestud.io/blog/retrofit-2-how-to-upload-files-to-server 我在仅使用一个文件时设法成功实现了它,但是我希望在一个会话中所有用户选择的图像都上传到服务器。
环顾四周,我发现 "Retrofit" multiple images attached in one multipart request 那里讨论了 @partmap 注释,这似乎是正确的匹配,但是我不明白我将如何迭代我需要上传的图像?
谁能告诉我正确的实施方式?
还检查了:
1.
2.Upload multiple image with same name as array Retrofit 2.0.0-beta2
我只是想解决一个类似的案例,但我有大量的文件。
我试过用循环来解决它:
recordsDirectory.mkdirs();
final File[] list_files = recordsDirectory.listFiles();
int cont = list_files.length;
for (int i = 0; i < cont; i++) {
final File ref_file = list_files[i];
String source_filepath = ref_file.getPath();
RequestBody requestBody =
RequestBody.create(MediaType.parse("multipart/form-data"), ref_file);
Call<DeliveryResponse> call = apiService.upload(requestBody, description);
call.enqueue(new Callback<DeliveryResponse>() {
@Override
public void onResponse(Response<DeliveryResponse> response, Retrofit retrofit) {
Log.v(TAG, "[" + TAG + "] Upload success. status: " + response.toString());
DeliveryResponse deliveryResponse = response.body();
Log.v(TAG, "response code: " + deliveryResponse.mStatus);
Log.v(TAG, "response code: " + response.code());
Log.v(TAG, "ref_file: " + ref_file.getPath());
if (response.isSuccess()) {
Log.i(TAG, "[" + TAG + "] The server has response with a status distinct to 200.");
}
else {
if (deliveryResponse.mStatus == 1) {
Log.i(TAG, "[" + TAG + "] The server has response with 1 as status.");
boolean deleted = ref_file.delete();
} else {
Log.i(TAG, "[" + TAG + "] The server has response with 0 as status.");
}
}
}
@Override
public void onFailure(Throwable t) {
Log.e("Upload", t.getMessage());
}
});
}
/***********************************************
RETROFIT API
************************************************/
public interface MyApiEndpointInterface {
@Multipart
@POST("/elderbask/api/sensors/accelerometer")
Call<DeliveryResponse> upload(
@Part("myfile\"; filename=\"image.png\" ") RequestBody file,
@Part("description") String description
);
}
public static class DeliveryResponse {
@SerializedName("status")
int mStatus;
public DeliveryResponse(int status) {
this.mStatus = status;
}
public String toString(){
return "mStatus: " + this.mStatus;
}
}
但是这个解决方案并不像我预期的那样有效。我有很多超时异常,错误的硬编码文件名非常糟糕。
由于我没有设法使用改造解决问题,所以我最终使用了 okhttp 库,它给了我我需要的东西,这里是我使用的代码示例,我希望它能帮助别人
构建请求正文:
okhttp3.RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addPart(okhttp3.Headers.of("Content-Disposition:", "form-data; name=\"myfile\"; filename=\"image" + ImageNumber + ".jpg\""),
okhttp3.RequestBody.create(MEDIA_TYPE_JPG, new File(ImagePath)))
.build();
准备请求:
request = new okhttp3.Request.Builder()
.header("Authorization", "Client-ID " )
.url(YOUR URL)
.post(requestBody)
.build();
启动与服务器的连接:
try {
okhttp3.Response response = client.newCall(request).execute();
if (!response.isSuccessful())
throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
哇哦!我做到了,你可以像我一样尝试这个(改造 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 file);
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
$f = fopen($pic, "w");
fwrite($f,$_POST['file']);
fclose($f);
$arr[] = array("result"=>"Done");
print(json_encode($arr));
?>
我目前正在处理应用程序的一部分,用户需要从图库中选择一些图像,然后将这些图像上传到服务器。对于上传,我使用的是使用 multipart 的改造 2.0。
根据资源 https://futurestud.io/blog/retrofit-2-how-to-upload-files-to-server 我在仅使用一个文件时设法成功实现了它,但是我希望在一个会话中所有用户选择的图像都上传到服务器。
环顾四周,我发现 "Retrofit" multiple images attached in one multipart request 那里讨论了 @partmap 注释,这似乎是正确的匹配,但是我不明白我将如何迭代我需要上传的图像?
谁能告诉我正确的实施方式?
还检查了:
1.
我只是想解决一个类似的案例,但我有大量的文件。
我试过用循环来解决它:
recordsDirectory.mkdirs();
final File[] list_files = recordsDirectory.listFiles();
int cont = list_files.length;
for (int i = 0; i < cont; i++) {
final File ref_file = list_files[i];
String source_filepath = ref_file.getPath();
RequestBody requestBody =
RequestBody.create(MediaType.parse("multipart/form-data"), ref_file);
Call<DeliveryResponse> call = apiService.upload(requestBody, description);
call.enqueue(new Callback<DeliveryResponse>() {
@Override
public void onResponse(Response<DeliveryResponse> response, Retrofit retrofit) {
Log.v(TAG, "[" + TAG + "] Upload success. status: " + response.toString());
DeliveryResponse deliveryResponse = response.body();
Log.v(TAG, "response code: " + deliveryResponse.mStatus);
Log.v(TAG, "response code: " + response.code());
Log.v(TAG, "ref_file: " + ref_file.getPath());
if (response.isSuccess()) {
Log.i(TAG, "[" + TAG + "] The server has response with a status distinct to 200.");
}
else {
if (deliveryResponse.mStatus == 1) {
Log.i(TAG, "[" + TAG + "] The server has response with 1 as status.");
boolean deleted = ref_file.delete();
} else {
Log.i(TAG, "[" + TAG + "] The server has response with 0 as status.");
}
}
}
@Override
public void onFailure(Throwable t) {
Log.e("Upload", t.getMessage());
}
});
}
/***********************************************
RETROFIT API
************************************************/
public interface MyApiEndpointInterface {
@Multipart
@POST("/elderbask/api/sensors/accelerometer")
Call<DeliveryResponse> upload(
@Part("myfile\"; filename=\"image.png\" ") RequestBody file,
@Part("description") String description
);
}
public static class DeliveryResponse {
@SerializedName("status")
int mStatus;
public DeliveryResponse(int status) {
this.mStatus = status;
}
public String toString(){
return "mStatus: " + this.mStatus;
}
}
但是这个解决方案并不像我预期的那样有效。我有很多超时异常,错误的硬编码文件名非常糟糕。
由于我没有设法使用改造解决问题,所以我最终使用了 okhttp 库,它给了我我需要的东西,这里是我使用的代码示例,我希望它能帮助别人
构建请求正文:
okhttp3.RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addPart(okhttp3.Headers.of("Content-Disposition:", "form-data; name=\"myfile\"; filename=\"image" + ImageNumber + ".jpg\""),
okhttp3.RequestBody.create(MEDIA_TYPE_JPG, new File(ImagePath)))
.build();
准备请求:
request = new okhttp3.Request.Builder()
.header("Authorization", "Client-ID " )
.url(YOUR URL)
.post(requestBody)
.build();
启动与服务器的连接:
try {
okhttp3.Response response = client.newCall(request).execute();
if (!response.isSuccessful())
throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
哇哦!我做到了,你可以像我一样尝试这个(改造 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 file);
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
$f = fopen($pic, "w");
fwrite($f,$_POST['file']);
fclose($f);
$arr[] = array("result"=>"Done");
print(json_encode($arr));
?>