最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to upload photo to AWS S3 using the Fetch API? - Stack Overflow

programmeradmin1浏览0评论

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. I am getting the presigned post url and the file details correctly but I believe the way I am formatting the formData is incorrect.

I'm using an html file input that uses onchange to run a javascript function handlePhoto.

The html is

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

and javascript function is

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.

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. I am getting the presigned post url and the file details correctly but I believe the way I am formatting the formData is incorrect.

I'm using an html file input that uses onchange to run a javascript function handlePhoto.

The html is

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

and javascript function is

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.

Share Improve this question edited May 13, 2020 at 18:06 Harry Moreno 11.6k8 gold badges73 silver badges119 bronze badges asked May 7, 2020 at 2:03 Jordan GreenbergJordan Greenberg 1991 silver badge4 bronze badges 3
  • 1 Don't use mode: "no-cors". The S3 API supports CORS access – Phil Commented May 7, 2020 at 2:07
  • 2 How do you know what the response is from your POST request? You don't have anything handling the response at all. If you can see the response status somehow, what is the response text? – Phil Commented May 7, 2020 at 2:12
  • 1 I can see the request headers and payload using the Chrome Developer tools in my browser. The information is linked in these screenshots. Headers :i.imgur./FptTWU7.png Request Payload: i.imgur./jaN61lo.png – Jordan Greenberg Commented May 7, 2020 at 15:02
Add a ment  | 

4 Answers 4

Reset to default 2

Assuming you have a presigned url you could use something like this:

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

export function uploadToS3(params: UploadToS3Params) {
  const { file, url } = params;
  return fetch(url, {
    body: file,
    mode: "cors",
    method: "PUT",
    // optional headers
    // headers: { "Content-Type": "text/plain" },
  });
}

check the url in s3Result, for me it was wrong link and it doesn't include my bucketname. url must be like this to work:

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

Your URL might not be right, From the documentation, hostnames should look something like this. "s3.Region.amazonaws.".

These two links might help https://docs.aws.amazon./AmazonS3/latest/userguide/RESTAPI.html and, https://docs.aws.amazon./AmazonS3/latest/API/sigv4-HTTPPOSTForms.html

You don't need to use a FormData, just pass the file with a content-type 'octet-stream'.

acl must be used when generating the presign URL.

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

评论列表(0)

  1. 暂无评论