I am trying to upload a file (taken by my device's camera) to Amazon S3. Unfortunately, the request fails with an InvalidArgument exception:
<Code>InvalidArgument</Code><Message></Message><ArgumentName>x-amz-acl</ArgumentName>
The request should take the form of:
------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--
I have the Retrofit logger enabled, however unfortunately it does not output the request body.
I do not set x-amz-acl
in my header.
My service is as follows:
public interface FileUploadService {
@Multipart
@POST("/")
Call<FileUpload> upload(@PartMap LinkedHashMap<String,String> params, @Part MultipartBody.Part file);
}
Inside my camera fragment, I do:
// 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
}
});
The parameters from the URL request are all correct.
If you don't mind an alternative approach to your problem, please let me suggest the following approach.
commons-net-3.4.jar
from apache commons website libs/
folder. build.gradle
file and ready for use. When you are ready, regardless of which approach you want to do the background operation of uploading the file, you can use the following sample code:
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; }
Since you have to get the file location from your device, you can simply pass it as a param to the async task or even a service. When the operation is completed, you can update the UI accordingly using events or something you like.
Using the commons
library is much easier and faster in my opinion because you only need to write a few lines of code!
I hope this helps you solve your issue and good luck!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.