如何在flutter中将图像上传到s3预签名URL?

Zha*_* Yi 5 amazon-s3 flutter

我在打字稿中创建了一个 s3 预签名 URL,如下所示:

const params = {
      Bucket: myBucketName,
      Key: uuidv4(),
      Expires: 3600,
    };
s3.getSignedUrlPromise('putObject', params)
Run Code Online (Sandbox Code Playgroud)

我在 flutter 中使用以下代码将图像上传到此网址:

选项1:

var formData = FormData.fromMap({
      "file":
          await MultipartFile.fromFile(image.path, filename: "upload.png"),
    });
    var response = await Dio().put(url, data: formData);
Run Code Online (Sandbox Code Playgroud)

选项2:

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 %");
      },
    )
Run Code Online (Sandbox Code Playgroud)

在这两种情况下我都得到了403禁止的错误响应。如何将图片上传到预先指定的URL?生成端或者flutter端有什么问题吗?

curl我可以使用如下命令上传文件:

 curl -XPOST -H "Content-Type: application/x-www-form-urlencoded"  --data-binary "@/Users/Pictures/IMG_4634.jpg" $PRESIGNED_URL
Run Code Online (Sandbox Code Playgroud)

所以这个网址确实有效。

小智 6

我已经尝试了该线程中的所有解决方案,但它不起作用

最后我找到了这个博客:https ://iCircuit.net/flutter-upload-file-to-aws-s3/2885

这是与 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;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我创建了这个类来使用预签名的 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;

  }
}
Run Code Online (Sandbox Code Playgroud)

如果您使用的是文件,则可以更改await file.readAsBytes()为此file.readAsBytesSync()


ste*_*din 2

如果您可以以某种方式打印 S3 的响应,则可能会显示错误。

从现有信息来看,我认为问题在于您使用的是 PUT 请求而不是 POST 请求。查看 Dio 文档,似乎您可以使用Dio().post. 您可能还需要Content-Type像卷曲示例中那样进行设置。

如果仍然不起作用,请尝试添加-v到您的curl命令中以查看它发送的所有标头。获取 Dio 发送的网络请求进行比较会很有用。