'How to upload images to s3 presigned URL in flutter?
I create a s3 presigned URL in typescript as below:
const params = {
Bucket: myBucketName,
Key: uuidv4(),
Expires: 3600,
};
s3.getSignedUrlPromise('putObject', params)
and I used below code in flutter to upload image to this url:
Option1:
var formData = FormData.fromMap({
"file":
await MultipartFile.fromFile(image.path, filename: "upload.png"),
});
var response = await Dio().put(url, data: formData);
Option2:
return Dio().put(
url,
data: image.openRead(),
options: Options(
contentType: "multiple/form-data",
headers: {
"Content-Length": image].lengthSync(),
},
),
onSendProgress: (int sentBytes, int totalBytes) {
double progressPercent = sentBytes / totalBytes * 100;
print("upload $progressPercent %");
},
)
in both cases I got 403 forbidden error response. How can I upload images to the presigned URL? Is there anything wrong in the generated side or flutter side?
I can upload the file with curl command like below:
curl -XPOST -H "Content-Type: application/x-www-form-urlencoded" --data-binary "@/Users/Pictures/IMG_4634.jpg" $PRESIGNED_URL
so the url does work.
Solution 1:[1]
I was getting 403 doing the same thing with presigned s3 urls and had to use a POST request which returned a 204 and successfully saved the file.
Using the http package I did the example like so:
import 'package:http/http.dart' as http;
var req = http.MultipartRequest('POST', Uri.parse(s3Url));
req.files.add(
http.MultipartFile.fromBytes(
'file',
file.readAsBytesSync(),
filename: filename,
)
);
var res = await req.send();
print('UPLOAD: ${res.statusCode}');
This returns a StreamedResponse type so to get the body of the response you need to convert the response.
NOTE: I did have to add a lot of fields on the multipart request like AWSAccessKeyId and x-amz-security-token which I was returning from the s3 presigned URL response. I configured it very securely though so you may not need that but wanted to clarify.
Solution 2:[2]
I created this class to send an single image to s3 using pre-signed url, I'm using camera lib to send a photo to s3.
import 'dart:convert';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:http/http.dart';
import 'package:http_parser/http_parser.dart';
class AwsApi {
Future<String> uploadToSignedUrl({required XFile file, required String signedUrl}) async {
Uri uri = Uri.parse(signedUrl);
var response = await put(uri, body: await file.readAsBytes(), headers: {"Content-Type": "image/jpg"});
return response;
}
}
You can change await file.readAsBytes() to this file.readAsBytesSync(), if you are using File
Solution 3:[3]
If you can print the response from S3 somehow, that may reveal the error.
From the information available, I think the problem is that your are using a PUT request and not a POST request. Looking at the Dio documentation, it seems like you can use Dio().post. You may also need to set Content-Type like in your curl example.
If it still doesn't work, try adding -v to your curl command to see all of the headers it sends. It would be useful to get the network request that Dio sends, to compare against.
Solution 4:[4]
After some debugging, I found that this code can be used to fix it:
http.put(entry.value, body: image.readAsBytesSync())
I don't need to specify any header or any fields. And http.post is google enough to solve the issue.
Solution 5:[5]
I have tried all the solutions in this thread but it's not working
finally i found this blog: https://icircuit.net/flutter-upload-file-to-aws-s3/2885
this is the solution that works great with Dio:
Future<Response> sendFile(String url, File file) async {
Dio dio = new Dio();
var len = await file.length();
var response = await dio.put(url,
data: file.openRead(),
options: Options(headers: {
Headers.contentLengthHeader: len,
} // set content-length
));
return response;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Nicholas Pesa |
| Solution 2 | Jonatas Campos Martins |
| Solution 3 | stefansundin |
| Solution 4 | Joey Yi Zhao |
| Solution 5 | Gil Porsansky |
