Edgar C Garzon
Edgar C Garzon

Reputation: 51

AWS S3 update image using pre-signed URL (Axios-PUT Request)

I'm trying to update a local JPG image file into an S3 bucket using the REST PUT request and Axios.

I managed to send the PUT request and to get a positive answer from AWS S3 Service but what it's been upload is not a JPG file but a JSON file.

This is the code that I'm using:

    //Create the FormData
    var data = new FormData();
    data.append('file', fs.createReadStream(image_path));


   //Send the file to File-system
   console.log("Sending file to S3...");
   const axiosResponse = await axios.put(image_signed_url, {
       data: data,
       headers: { 'Content-Type': 'multipart/form-data' }
     }).catch(function(error) {
      console.log(JSON.stringify(error));
      return null;
     });

I have already try to change the headers to {'Content-Type': 'application/octet-stream' } but I obtained the same result.

Upvotes: 2

Views: 5005

Answers (2)

devansvd
devansvd

Reputation: 1009

AXIOS Version:

When using with Axios Don't send it as FormData send it directly else Signature mismatch error.

const s3PUTSignedURL = (url: string, data: any) => {
        return new Promise((resolve, reject) => {
           //file Stream without formData as second parameter
            axios.put(url, data, {
                headers: {
                    'Content-Type': data.type,
                }
            })
                .then((response) => {
                    console.log(JSON.stringify(response.data));
                    return resolve(response);
                })
                .catch((error) => {
                    console.log(error);
                    return reject(error);
                });
        });
    };

Ref: https://github.com/axios/axios/discussions/4478#discussioncomment-2178622

Ref: https://stackoverflow.com/a/57689819/6333644

FETCH version:

When using with Fetch sending FormData and Without FormData both works. Not sure why.

const s3PUTSignedURL = (url: string, data: any) => {
    return new Promise((resolve, reject) => {
        const headers = new Headers();
        headers.append('Content-Type', data.type);

        const formdata = new FormData();
        formdata.append('', data);

        const requestOptions = {
            method: 'PUT',
            headers: headers,
            body: formdata, //formdata or data both works
        };

        fetch(url, requestOptions)
            .then((response) => response.text())
            .then((result) => resolve(result))
            .catch((error) => reject(error));
    });
};

Upvotes: 0

Edgar C Garzon
Edgar C Garzon

Reputation: 51

It did not manage to make AXIOS work in order to upload an image.

The node-fetch module did it sending the image as a binary and specifying the "Content-type".

If I try to the same using AXIOS it the image was always packet into a form-data and the result was JSON file uploaded into the S3 bucket instead of the image.

 //Send the file to File-system
console.log("Sending file to S3...");
const resp = await fetch(image_signed_url, {
    method: 'PUT',
    body: fs.readFileSync(image_path),
    headers: {
      'Content-Type': 'image/jpeg',
  },
}).catch( err => {
  console.log(err);
  return null;
});

Upvotes: 3

Related Questions