在Android上使用Retrofit2将文件上传到Amazon S3时出现问题

时间:2016-05-11 12:45:59

标签: java android amazon-s3 retrofit2

我正在尝试将文件(由我设备的相机拍摄)上传到Amazon S3。不幸的是,请求因InvalidArgument异常而失败:

------WebKitFormBoundaryPJf5u1BglONosgFh
Content-Disposition: form-data; name="key"

uploads/FooBar/<SOME ID>/db8218d9-2e45-4ed4-bd44-70019bbf6047_${filename}
------WebKitFormBoundaryPJf5u1BglONosgFh
Content-Disposition: form-data; name="success_action_status"

201
------WebKitFormBoundaryPJf5u1BglONosgFh
Content-Disposition: form-data; name="acl"

public-read
------WebKitFormBoundaryPJf5u1BglONosgFh
Content-Disposition: form-data; name="Expires"

Wed, 11 May 2016 13:26:28 GMT
------WebKitFormBoundaryPJf5u1BglONosgFh
Content-Disposition: form-data; name="file"; filename="blob"
Content-Type: image/png


------WebKitFormBoundaryPJf5u1BglONosgFh--

请求应采取以下形式:

x-amz-acl

我启用了Retrofit记录器,但不幸的是它没有输出请求体。

我没有在标题中设置 public interface FileUploadService { @Multipart @POST("/") Call<FileUpload> upload(@PartMap LinkedHashMap<String,String> params, @Part MultipartBody.Part file); }

我的服务如下:

// Get my image
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);

RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), bytes);
MultipartBody.Part body = MultipartBody.Part.createFormData("file","filename.jpg", requestFile);

// Get parameters from upload URL request
LinkedHashMap<String, String> params = response.body().getFields();


uploadService.upload(params, body).enqueue(new Callback<FileUpload>() {

         @Override
         public void onResponse(Call<FileUpload> call, Response<FileUpload> response) {
              // DO STUFF
         }

         @Override
         public void onFailure(Call<FileUpload> call, Throwable t) {
             // DO STUFF
         }
});

在我的相机片段中,我这样做:

{{1}}

来自网址请求的参数都是正确的。

1 个答案:

答案 0 :(得分:0)

如果您不介意解决问题的其他方法,请让我建议以下方法。

  • apache commons website
  • 下载commons-net-3.4.jar
  • 解压缩下载的文件后,将jar文件添加到libs/文件夹。
  • 然后右键单击 - &gt;将库添加到您的应用模块。应该是直截了当的。您会注意到它会将库添加到您的build.gradle文件中并可以使用。
  • 准备就绪后,无论您想要执行上传文件的后台操作,都可以使用以下示例代码:

    public class SyncFileToServer extends AsyncTask<String, Void, String>{
        @Override
        protected String doInBackground(String... params){
            FTPClient ftpClient = new FTPClient();
    
    
            try{
               ftpClient.connect("xxx.xxx.x.xxx");
               ftpClient.login("username", "password");
               ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
               ftpClient.enterLocalPassiveMode();
    
               File file = new File("path/to/file");
    
               FileInputStream inputStream = new FileInputStream(file);
    
              if(ftpClient.storeFile("filetotransfer", inputStream)){
                  ftpClient.disconnect();
                  return "success";
              }else{
                  ftpClient.disconnect();
                  return "ERROR";
              }
            }catch (IOException e){ e.printStackTrace(); }
        }
    
        return null;
    }
    

由于您必须从设备获取文件位置,因此您只需将其作为参数传递给异步任务甚至服务即可。操作完成后,您可以使用您喜欢的事件或相应内容相应地更新UI。

在我看来,使用commons库更容易,更快,因为您只需编写几行代码!

我希望这可以帮助您解决问题并祝您好运!