android - 无法在 Android 中使用改造在多部分/表单数据请求中上传多个文件或文件集合

标签 android file-upload retrofit multipartform-data retrofit2

我正在开发 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);
}

如您所见,我正在尝试将文件列表作为第一个参数上传。

这是我在 Activity 中上传的方式

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。你可以看到下面的截图。它始终为空。你在服务器端像这样绑定(bind)。

public JsonResult CreateMemePost(IEnumerable<HttpPostedFileBase> files,CreateMemePostModel model)

文件始终为空,并且模型中的 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);
}

我在 Activity 中创建这样的 map

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

文件在服务器上始终为空。

最佳答案

最后,我找到了解决方案。我使用了 RequestBody 和 MultipartBody.Builder。我在 Github 上上传了解决方案。

请查看此链接 - https://github.com/waiyanhein/how-to-upload-multiple-files-using-retrofit-in-android .

关于android - 无法在 Android 中使用改造在多部分/表单数据请求中上传多个文件或文件集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40000717/

相关文章:

javascript - plupload - 发送另一个带有上传文件的请求参数

android - 使用下载的图像作为通知图标

node.js - 如何使用nodejs在mongodb内上传多个文件

php - 在 php 中开源文件托管/共享

java - ORMLite 数据库模型通过改造适配器转为 GSON 错误; java.lang.IllegalStateException

java - Robospice-改造测试

android - 定期调用一个可观察对象并仅在下一个成功时切换到下一个

安卓 : Time milliseconds to X day - X hours - x Minute - X seconds left

java - Canvas 上文本的持续时间

java - 使用语音命令搜索