我正在使用Flutter App,使用预签名URL将图像文件(PUT请求)上传到AWS S3。我可以在S3中看到文件,因此上传成功。但是,当我单击并从存储桶中下载它时,下载的文件已损坏。
我正在使用Dio库上载文件。 通过邮递员将图像文件上传为二进制文件效果很好
uploadFileToPresignedS3(
File payload, String fileName, String presignedURL) async {
try {
Dio dio = new Dio();
FormData formData = new FormData.from(
{"name": fileName, "file1": new UploadFileInfo(payload, fileName)});
dio.put(presignedURL, data: formData);
} catch (ex) {
print(ex);
}
}
预期:上传的文件不会被破坏
实际结果:上传的文件已损坏
答案 0 :(得分:4)
使用此代码使用Dio将文件(图像)上传到S3预先签名的网址,并显示上传进度:
await dio.put(
url,
data: image.openRead(),
options: Options(
contentType: "image/jpeg",
headers: {
"Content-Length": image.lengthSync(),
},
),
onSendProgress: (int sentBytes, int totalBytes) {
double progressPercent = sentBytes / totalBytes * 100;
print("$progressPercent %");
},
);
注意:请勿像这样设置 Content-Type 标头和 Content-Length :
headers: {
"Content-Length": image.lengthSync(),
"Content-Type": "image/jpeg",
},
由于某些原因,它将导致上传的文件损坏。
以防万一:代替print("$progressPercent %")
,您可以使用setState()
在UI中显示更新。
希望这会有所帮助。
答案 1 :(得分:0)
要收回 Rabi Roshans 的评论,您需要将contenType修改为“ application / octet-stream”。在后端的S3参数中,您需要执行相同的操作。
客户代码
await dio.put(
url,
data: image.openRead(),
options: Options(
contentType: "application/octet-stream",
headers: {
"Content-Length": image.lengthSync(),
},
),
onSendProgress: (int sentBytes, int totalBytes) {
double progressPercent = sentBytes / totalBytes * 100;
print("$progressPercent %");
},
);
s3后端
var presignedUrl = s3.getSignedUrl("putObject", {
Bucket: "your_bucke_name",
Key: "filename.ext",
Expires: 120, // expirations in seconds
ContentType: "application/octet-stream", // this must be added or you will get 403 error
})
;
答案 2 :(得分:0)
我创建了这个类来使用预先签名的 url 将图像发送到 s3,我正在使用相机库将照片发送到 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;
}
}