【发布时间】:2017-02-21 09:07:45
【问题描述】:
我正在开发一个 Android 应用程序。在我的应用程序中,我需要在 multipart/form-data 请求中将多个文件或文件集合上传到服务器。我正在使用 Retrofit 2。我可以将单个文件上传到服务器。但是当我上传文件列表时,服务器端的文件值始终为空。
这是我改造的服务接口
public interface ApiService {
@Multipart
@POST("Troll/CreateMemePost")
Call<ResponseBody> postMeme(@Part List<MultipartBody.Part> files, @Part("AuthToken") RequestBody authToken);
}
如您所见,我正在尝试上传文件列表作为第一个参数。
这就是我在活动中上传的方式
final ArrayList<File> photoFiles = new ArrayList<File>();
ArrayList<MultipartBody.Part> files = new ArrayList<MultipartBody.Part>();
for(Bitmap bitmap: previewBitmaps)
{
File file = null;
try{
String fileName = String.valueOf(System.currentTimeMillis())+".jpeg";
file = new File(Environment.getExternalStorageDirectory(), fileName);
if(file.exists())
{
file.delete();
}
OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
os.close();
photoFiles.add(file);
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"),file);
MultipartBody.Part partFile = MultipartBody.Part.createFormData("multipart/form-data",file.getName(),requestFile);
files.add(partFile);
}
catch (Exception e)
{
Toast.makeText(getBaseContext(),e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
if(files!=null && files.size()>0)
{
final Retrofit retrofit = app.getApiClient().getRetrofit();
ApiService service = app.getApiClient().getApiService();
RequestBody authToken = RequestBody.create(MediaType.parse("multipart/form-data"), app.getAuthToken());
Call<ResponseBody> call = service.postMeme(files,authToken);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(photoFiles!=null && photoFiles.size()>0)
{
for(File tempFile : photoFiles)
{
if(tempFile.exists())
{
tempFile.delete();
}
}
}
if(response!=null)
{
if(response.isSuccessful())
{
Toast.makeText(getBaseContext(),"File Uploaded successfully",Toast.LENGTH_SHORT).show();
}
else if(!response.isSuccessful() && response.errorBody()!=null)
{
Toast.makeText(getBaseContext(),"Server error message",Toast.LENGTH_SHORT).show();
/*try{
}
catch (IOException e)
{
Toast.makeText(getBaseContext(),e.getMessage(),Toast.LENGTH_SHORT).show();
}*/
}
}
else{
Toast.makeText(getBaseContext(),"Response is null",Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
if(photoFiles!=null && photoFiles.size()>0)
{
for(File tempFile : photoFiles)
{
if(tempFile.exists())
{
tempFile.delete();
}
}
}
Toast.makeText(getBaseContext(),"Unable to transfer data to server",Toast.LENGTH_SHORT).show();
}
});
}
但是当我上传时,我在服务器端成功接收到 AuthToken 字段。但文件值始终为空。我正在使用 ASP.NET MVC 作为后端。你可以看到下面的截图。它始终为空。你在服务器端这样绑定。
public JsonResult CreateMemePost(IEnumerable<HttpPostedFileBase> files,CreateMemePostModel model)
files 始终为空,并且模型中的 AuthToken 字段作为从我的应用程序发送的存在。当我像这样上传单个文件时
public JsonResult CreateMemePost(HttpPostedFileBase file,CreateMemePostModel model)
它正在工作并成功上传。我很确定问题出在我的改造代码上。我的代码有什么问题?如何使用 Android 中的改造将文件列表上传到多部分/表单数据请求中的服务器?
我也尝试过仅上传文件
public interface ApiService {
@FormUrlEncoded
@POST("Troll/CreateMemePost")
Call<ResponseBody> postMeme(@Field("files") ArrayList<RequestBody> files);//, @Part("AuthToken") RequestBody authToken);
}
服务器端的文件数始终为 0。
然后我尝试了另一种使用 MapPart 的解决方案
public interface ApiService {
@Multipart
@POST("Troll/CreateMemePost")
Call<ResponseBody> postMeme(@PartMap() Map<String,RequestBody> files, @Part("AuthToken") RequestBody authToken);
}
我在活动中创建这样的地图
HashMap<String,RequestBody> map = new HashMap<>();
// Other steps
MediaType MEDIA_TYPE=MediaType.parse("multipart/form-data");
bodyFile = RequestBody.create(MEDIA_TYPE,file);
map.put("files",bodyFile);
文件在服务器上始终为空。
【问题讨论】:
标签: android file-upload retrofit multipartform-data retrofit2