首页 > 解决方案 > 在 React 中使用 Axios 上传到 S3 (PUT) 时数据损坏

问题描述

使用以下功能,我可以将图像上传到 S3,但是当我尝试检索图像时无法打开图像。以下是 React 应用程序中使用的函数,它使用“react-dropzone”处理文件:

import axios, { post } from 'axios'

import { Buffer } from 'buffer'

const processImage = ({ file }) => {
  const reader = new FileReader()

  reader.onload = async () => {
    const base64data = reader.result
    const bufferdata = Buffer.from(base64data, 'base64')


    const generateSignedS3Url = '/.netlify/functions/get-s3-urls'

    // Obtains signed URLs from a Netlify Serverless Function
    const { data } = await post(generateSignedS3Url, {
      clientFilename: file.name,
      mimeType: file.type,
    }).catch(e => {
      console.error('Error in generating signed url ', e)
    })

    axios({
      method: 'PUT',
      url: data.putUrl,
      data: bufferdata,
      headers: { 'Content-Type': file.type, 'Content-Encoding': 'base64' },
    }).catch(e => {
      console.error(e) 
    })
  }
  reader.readAsDataURL(file)
}

以下包含用于获取上面调用的无服务器函数的签名 URL 的参数:

const putParams = {
      Bucket,
      Key,
      Expires: 2 * 60,
      ContentType: body.mimeType,
      ContentEncoding: 'base64',
    }
    const putUrl = s3.getSignedUrl('putObject', putParams)

在这里,body.mimeType将是'image/jpeg'

从类似的 Stack Overflow 问题中扫描,我确保了以下几点:

  1. 标题'Content-Encoding'设置为'base64'
  2. 我正在使用缓冲区通过 NPM 缓冲区库发送内容(这是一个客户端应用程序)
  3. 标头'Content-Type'与正在发送的文件相匹配(即对于文件“background.jpg”,标头设置为“image/jpeg”)
  4. 我也尝试在没有缓冲区的情况下发送

在提交之前,我已经查看了类似的 SO 问题。它们包括123。还有其他的,但它们用于 Node 后端。

标签: reactjsimagehttpamazon-s3axios

解决方案


reader.result在编码数据之前有一个前缀。如MDN上所述:

如果不首先删除 Base64 编码数据之前的 Data-URL 声明,则无法将 blob 的结果直接解码为 Base64。要仅检索 Base64 编码的字符串,请首先data:*/*;base64,从结果中删除。

因此,您可以执行以下操作:

const base64data = reader.result.split(',')[1];

推荐阅读