'AWS S3/IAM CORS/Prefetch error when Uploading Image

I'm having problems setting up an S3 and IAM so that I can upload media files to the bucket. I've been following a video (https://www.youtube.com/watch?v=yGYeYJpRWPM&t=485s), and it feels like I've done everything that he did, but I still get a CORS error. Basically what I've done is setup an IAM account to have a "putObject" policy on my bucket, and then when the user uploads an image in the UI, I get the secured URL from the aws-sdk using my IAM credentials. Next, I then make a PUT request to the secured URL, with the file name as the Key. But that's when I get the cors error.

// frontend JS code
const form = document.querySelector("#form");
const input = document.querySelector("#file");
let url;

form.addEventListener("submit", async (e) => {
  e.preventDefault();
  const file = input.files[0];

  if (input.files.length) {
    const data = await fetch(
      "https://my-bucket-name.com/api/upload-image",
      {
        method: "POST",
        body: JSON.stringify({ fileName: input.files[0].name }),
        headers: {
          "Content-Type": "application/json",
        },
      }
    );

    const reponse = await data.json();

    url = reponse.url;

    if (url) {
      const data = await fetch(url, {
        method: "PUT",
        body: file,
        headers: {
          "Content-Type": "multipart/form-data",
        },
      });

      console.log("DATA", data);
    } else {
      console.log("no file");
    }
  }
});



// which uses this router on the express server
require("dotenv").config();
const express = require("express");
const router = express.Router();
const { s3 } = require("../../s3");

router.post("/upload-image", (req, res) => {
  console.log(req.body.fileName);
  s3.getSignedUrl(
    "putObject",
    {
      Bucket: process.env.AWS_BUCKET_NAME,
      Key: req.body.fileName,
      Expires: 60,
    },
    (err, url) => {
      if (err) {
        console.log("\nerror", err, "\n");
        return res.status(500).json({ error: err });
      }
      console.log("\nurl", url, "\n");
      res.status(200).json({ url });
    }
  );
});

module.exports = router;

// the s3 file above is simply this...
require("dotenv").config();
const aws = require("aws-sdk");

const s3 = new aws.S3({
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  region: process.env.REGION,
});

module.exports = {
  s3,
};

/*Bucket Policy
{
    "Version": "2012-10-17",
    "Id": "policyIDNumber",
    "Statement": [
        {
            "Sid": "bucket-sid",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-bucket-name/*"
        }
    ]
}
**/


/* Bucket CORS Policy
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT",
            "HEAD",
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]
**/
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Upload to S3 Bucket Test</title>
  </head>
  <body>
    <form id="form" accept="image/*">
      <input type="file" id="file" />
      <button>Submit</button>
    </form>
    <script src="./index.js"></script>
  </body>
</html>

IAM Policy IAM Policy

Edit: Actual Error Message Error Message



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source