简体   繁体   English

如何使用 Fetch API 将照片上传到 AWS S3?

[英]How to upload photo to AWS S3 using the Fetch API?

I am trying to upload a photo file to an S3 bucket using the Fetch API. I'm getting 400 Bad Request on the POST when trying to upload the photo.我正在尝试使用 Fetch API 将照片文件上传到 S3 存储桶。尝试上传照片时,我在 POST 上收到 400 Bad Request。 I am getting the presigned post url and the file details correctly but I believe the way I am formatting the formData is incorrect.我得到了预签名的帖子 url 和正确的文件详细信息,但我相信我格式化 formData 的方式不正确。

I'm using an html file input that uses onchange to run a javascript function handlePhoto.我正在使用 html 文件输入,它使用 onchange 来运行 javascript function handlePhoto。

The html is html 是

<input type="file" onchange="handlePhoto()" id="file_input"/>

and javascript function is和 javascript function 是

function handlePhoto(){
    const file = document.getElementById('file_input').files[0]
    let formData = new FormData()
    fetch("/v1/photos/get_presigned_post/" , {
      method: "GET"
    })
    .then(response => response.json())
    .then(s3Result => {
      const { url, fields } = s3Result;
      Object.keys(s3Result.fields).forEach(key => {
        formData.append(key, s3Result.fields[key]);
      });
      formData.append('acl', 'public-read');
      formData.append('Content-Type', file.type);
      formData.append("file", file);

      fetch(url, {
        method: "POST",
        body: formData,
        headers: {
          "Content-Type": "multipart/form-data"
        }
      })
  });
}

Any help would be greatly appreciated.任何帮助将不胜感激。

You don't need to use a FormData, just pass the file with a content-type 'octet-stream'.您不需要使用 FormData,只需使用内容类型“八位字节流”传递文件。

acl must be used when generating the presign URL.生成presign URL时必须使用acl。

fetch(url, {
                method: 'PUT',
                body: file,
                headers: { 'Content-Type': 'application/octet-stream' }
            })

Assuming you have a presigned url you could use something like this:假设你有一个预先签名的 url 你可以使用这样的东西:

interface UploadIAToS3Params {
  url: string;
  file: File;
}

export function uploadToS3(params: UploadIAToS3Params) {
  const { file, url } = params;
  return fetch(url, { body: file, mode: "cors", method: "PUT" });
}

check the url in s3Result, for me it was wrong link and it doesn't include your bucketname.检查 s3Result 中的 url,对我来说这是错误的链接,它不包含您的存储桶名称。 it must be like this to work:它必须像这样才能工作:

https://{bucket_name}.s3.amazonaws.com

Your URL might not be right, From the documentation, hostnames should look something like this.您的 URL 可能不正确,根据文档,主机名应如下所示。 "s3.Region.amazonaws.com". “s3.Region.amazonaws.com”。

These two links might help https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAPI.html and, https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTForms.html这两个链接可能对https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAPI.htmlhttps://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTForms 有帮助。 html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM