Search code examples
reactjsamazon-s3axiosxmlhttprequestpre-signed-url

Is there a way to upload image as binary data on pre-signed s3 PUT url using Axios or XHR


1) Code to generate s3 URL

      const file = req.files ? req.files.filename || null : null
      const extension = path.extname(file.name)
      const client = new S3Client()

      const params = {
        Bucket: S3_BUCKET, // env variable
        Key: `tmp/photos/image_file.png`,
        ContentDisposition: 'inline',
        ContentType: file.mimetype,
        Body: file.data
      }

      const command = new PutObjectCommand(params)
      const presignedS3Url = await getSignedUrl(client, command, { expiresIn: 3600 })

I am able to upload image with this CURL request

curl --location --request PUT $presignedS3Url \
--header 'Content-Disposition: inline' \
--header 'Content-Type: image/png' \
--data-binary '@/Users/name/Downloads/image-file.png'

Not able to upload using axios

      const imageFile = fs.readFile('/Users/filepath/image-file.png')
      const bufferString = Buffer.from(imageFile, 'base64')

      await axios.put(presignedS3Url, {
        data: bufferString
      }, {
        headers: {
          'Content-Type': file.mimetype,
          'Content-Disposition': 'inline'
        }
      })

How to use Axios or XHR to upload image?


Solution

  • While generating presigned URL use this

        const params = {
            Bucket: S3_BUCKET, // env variable
            Key: `tmp/photos/image_file.png`
          }
    

    To upload use XMLHttpRequest

        const s3Url = uploadedImageResponse?.item?.url || ''
        const xhr = new XMLHttpRequest()
        xhr.withCredentials = false
    
        xhr.upload.onprogress = event => {
          if (event.lengthComputable) {
            const percentComplete = (event.loaded / event.total) * 100
            progressHandler(percentComplete, fileName)
          }
        }
        xhr.onreadystatechange = async function () {
          if (xhr.readyState === 4) {
            if (xhr.status === 200) {
              await successHandler(uploadedImageResponse, fileName)
            } else {
              errorHandler('Error uploading file', fileName)
            }
          }
        }
        xhr.open('PUT', s3Url)
        xhr.send(file.file)