10 votes

J'ai téléchargé un fichier sur S3 via l'URL pré-signée de l'application Flutter, mais le fichier est corrompu lorsque je le télécharge.

Je travaille sur une application Flutter, dans laquelle je télécharge un fichier image (requête PUT) vers AWS S3 en utilisant une URL prédéfinie. Le téléchargement est réussi et je peux voir le fichier dans S3. Mais lorsque je clique et que je le télécharge depuis le bucket, le fichier téléchargé est corrompu.

J'utilise la bibliothèque Dio pour télécharger le fichier. Le téléchargement du fichier image en tant que binaire via postman fonctionne parfaitement.

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);
  }
}

Attendu : le fichier téléchargé ne soit pas corrompu

Résultat réel : Le fichier téléchargé est corrompu

14voto

Rabi Roshan Points 668

Utilisez ce code pour télécharger un fichier (image) vers S3 pre-signed-url en utilisant Dio et afficher progression du téléchargement :

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 %");
    },
  );

Note : Ne pas régler Content-Type ainsi que l'en-tête Longueur du contenu comme ceci :

headers: {
   "Content-Length": image.lengthSync(),
   "Content-Type": "image/jpeg",
},

Pour une raison quelconque, le fichier téléchargé sera corrompu.

Au cas où : Au lieu de print("$progressPercent %") vous pouvez utiliser setState() pour afficher les mises à jour dans l'interface utilisateur.

J'espère que cela vous aidera.

3voto

Luis Points 131

Pour s'inspirer de Rabi Roshans vous devez modifier contenType en "application/octet-stream". Dans les paramètres S3 de votre backend, vous devez faire la même chose.

code client

  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 %");
    },
  );

backend 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
  })

;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X