title: Uploading images to S3 with ContentType image/jpeg - nodejs and react?
body: <p>Chrome implement recently a new feature called <strong>CORB</strong> and its in some very rare case block my website to display images that are hosted in AWS S3.</p>
  
  <p>Investigating a bit the problem i discover that my images are currently sent with a <strong>header ContentType of application/x-www-form-urlencoded</strong> when it should be <strong>image/jpeg</strong>.
  In the amazon console you can update the metadata content-type of your whole bucket but unfortunately it doesn't apply to the new image that will be uploaded on the future.</p>
  
  <p><strong>So i wonder if i am doing something wrong in my code?</strong> (i will show some extract below) or if there is something can make possible to create a JOB/CRON in amazone to recursivly update the metadata content-type of the uploaded image to ensure this issue with the <strong>CORB</strong> doesn't happen?</p>
  
  <p>One of the solution would be to pass through an image optimizer handler such as <a href="https://imagekit.io/" rel="nofollow noreferrer">https://imagekit.io/</a> to fix the problem, but in the case of the avatar images that are coming from other source than amazon (it can come from gravatar, or facebook, or google also) i can't use such feature (unless writing a regex script that would check if the specific image came from amazon)</p>
  
  <p>i am using nodejs/express for the backend and react for the front. I don't upload the image on my server but directly from my front to amazon. To do so, i request a signedUrl from amazon and use it frontside to upload.</p>
  
  <p><strong>BACKEND:</strong></p>
  
  <pre><code>const AWS = require("aws-sdk")
  const router = express.Router()
  // CONFIG AMAZONE
  const s3 = new AWS.S3({
    accessKeyId: keys.aws.clientID,
    secretAccessKey: keys.aws.clientSecret,
    signatureVersion: "v4",
    region: "eu-west-3"
  })
  
  // @route  GET api/profile/avatar/upload
  // @desc   Upload your profile avatar
  // @access Private
  router.get(
    "/",
    passport.authenticate("jwt", { session: false }),
    (req, res) =&gt; {
      const key = `avatars/${req.user.id}/${uuid()}-avatar-image.jpeg`
      s3.getSignedUrl(
        "putObject",
        {
          Bucket: "mybucket",
          ContentType: "image/jpeg",
          Key: key.toString()
        },
        (err, url) =&gt; res.send({ key, url })
      )
    }
  )
  </code></pre>
  
  <p><strong>FRONTEND:</strong></p>
  
  <p>here i am using redux and axios library. This last one have an issue of compatibility header with amazon so you need to disable the default header in order to upload corretly your images</p>
  
  <pre><code>// UPDATE PROFILE PICTURE
  export const sendAvatar = file =&gt; async dispatch =&gt; {
    dispatch(loading())
    try {
      const uploadConfig = await axios.get("/api/global/avatar")
      delete axios.defaults.headers.common["Authorization"]
      console.log(uploadConfig)
      console.log(file)
      file &amp;&amp;
        (await axios.put(uploadConfig.data.url, file, {
          headers: {
            ContentType: file.type
          }
        }))
      const token = localStorage.getItem("jwtToken")
      axios.defaults.headers.common["Authorization"] = token
      const res = await axios.post("/api/global/avatar", {
        avatar: uploadConfig.data.key
      })
      dispatch({
        type: USER_AVATAR_FETCH,
        payload: res.data.avatar
      })
    } catch (e) {
      dispatch({
        type: GET_ERRORS,
        payload: e.response.data
      })
    }
    dispatch(clearLoading())
  }
  </code></pre>