【问题标题】:Downloading File using Axios then uploading to Amazon S3使用 Axios 下载文件然后上传到 Amazon S3
【发布时间】:2020-07-15 16:35:37
【问题描述】:

我在 SO 上看到了各种关于使用 Axios 下载文件并将它们上传到 S3 的问题,但没有一个能将它们联系在一起,我对流、blob、多部分表单等感到困惑。这是我的代码到目前为止.

正在下载文件。

const downloadResponse = await axios({
    url: `https://example.com/test.jpg`,
    method: 'GET',
    responseType: 'stream'   // Should this be blob, stream or arraybuffer?
})

目前不确定“downloadResponse.data”中包含什么,typeof 表明它是一个对象,而不是一个流

获得签名响应(这是通过 Storyblok CMS 而非亚马逊完成的)

const signedResponse = await axios.post(`https://api.storyblok.com/v1/spaces/xxx/assets`, {
    filename: 'test.jpg',
}, {
    headers: {'Authorization': 'xxxxx'}
})

使用表单数据包创建表单数据

let form = new FormData()

for (var key in signedResponse.fields) {
    form.append(key, signedResponse.fields[key])
}

try {
    form.append('file', fs.createReadStream(downloadResponse.data))
} catch (error) {
    console.log("Error Creating Data", error)
}

上传到 S3

try {
    
    const uploadResponse = await axios({
        method: 'post',
        url: signedResponse .data.post_url,
        data: form.getBuffer(),
        headers: form.getHeaders()
    })

} catch (error) {
    console.log("Error Uploading", error)
}

目前这在创建流时导致以下错误..

错误创建数据类型错误 [ERR_INVALID_ARG_TYPE]:“路径”参数必须是字符串、缓冲区或 URL 类型之一。接收到的类型对象。

我尝试直接从第一个请求中获取数据,而不是在其上使用 fs.createReadStream(),因为它应该已经是一个流,但会产生相同的错误。

我还尝试从第一个请求返回一个数组缓冲区并使用 Buffer.from() 然后附加缓冲区,但这也不起作用,我认为亚马逊给了我一个 400 错误,所以我迷路了。

任何帮助将不胜感激。

【问题讨论】:

标签: node.js amazon-s3 stream axios multipartform-data


【解决方案1】:

此代码使用 v3 版本的 AWS JS SDK。使用 Node v16(ES16 模块)

  1. 初始化 S3 客户端
// Ref: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/index.html
import { S3Client } from '@aws-sdk/client-s3';

// Constants
const accessKeyId = process.env.AWS_ACCESS_KEY
const secretAccessKey = process.env.AWS_SECRET_KEY
const awsRegion = 'ap-south-1';
export const awsBucket = process.env.AWS_BUCKET;

export const S3 = new S3Client({
  credentials: {
    accessKeyId,
    secretAccessKey,
  },
  region: awsRegion,
});
  1. 使用 Axios 下载。
    最重要的部分是使用responseType: 'arraybuffer'
const resp = await axios.get('https://domain/image/imagename.png', {   
  decompress: false,
  // Ref: https://stackoverflow.com/a/61621094/4050261
  responseType: 'arraybuffer',
})
  1. 使用 S3 客户端上传
import { PutObjectCommand } from '@aws-sdk/client-s3';
import { awsBucket, S3 } from '../lib/aws.js'; // Defined in Point 1 above

await S3.send(
  new PutObjectCommand({
    Bucket: awsBucket,
    Key: `foldername/filename`,
    Body: resp.data,
  })
)

【讨论】:

    猜你喜欢
    • 2011-11-10
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 2015-03-17
    • 2021-08-22
    • 1970-01-01
    相关资源
    最近更新 更多