通过Flutter App通过PreSigned URL将文件上传到S3。但我下载文件时文件已损坏

时间:2019-06-13 09:48:44

标签: amazon-web-services amazon-s3 flutter pre-signed-url

我正在使用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);
  }
}


预期:上传的文件不会被破坏

实际结果:上传的文件已损坏

3 个答案:

答案 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;

  }
}