【问题标题】:How to Upload files to Amazon AWS3 with NodeJS?如何使用 NodeJS 将文件上传到 Amazon AWS3?
【发布时间】:2019-11-22 09:48:20
【问题描述】:

我正在尝试从我正在开发的 MERN 应用程序上传文件。我几乎完成了 NodeJS 后端部分。

所述应用程序将允许用户将图像(jpg、jpeg、png、gif 等)上传到我创建的 Amazon AWS S3 存储桶。

好吧,让我们这样说。我创建了一个助手:

const aws = require('aws-sdk');
const fs = require('fs');

// Enter copied or downloaded access ID and secret key here
const ID = process.env.AWS_ACCESS_KEY_ID;
const SECRET = process.env.AWS_SECRET_ACCESS_KEY;

// The name of the bucket that you have created
const BUCKET_NAME = process.env.AWS_BUCKET_NAME;

const s3 = new aws.S3({
  accessKeyId: ID,
  secretAccessKey: SECRET
});

const uploadFile = async images => {
  // Read content from the file
  const fileContent = fs.readFileSync(images);

  // Setting up S3 upload parameters
  const params = {
    Bucket: BUCKET_NAME,
    // Key: 'cat.jpg', // File name you want to save as in S3
    Body: fileContent
  };

  // Uploading files to the bucket
  s3.upload(params, function(err, data) {
    if (err) {
      throw err;
    }
    console.log(`File uploaded successfully. ${data.Location}`);
  });
};

module.exports = uploadFile;

那个助手接受了我的三个环境变量,它们是存储桶的名称、keyId 和密钥。

从表单添加文件时(最终将添加到前端),用户将能够发送多个文件。

现在我当前的发布路线看起来就像这样:

req.body.user = req.user.id;
req.body.images = req.body.images.split(',').map(image => image.trim());
const post = await Post.create(req.body);

res.status(201).json({ success: true, data: post });

那里的效果很好,但将 req.body.images 作为字符串,每个图像用逗号分隔。正确的方法是上传(到 AWS S3)从 Windows 目录弹出的许多文件?我试过这样做但没有用:/

// Add user to req,body
req.body.user = req.user.id;
uploadFile(req.body.images);
const post = await Post.create(req.body);

res.status(201).json({ success: true, data: post });

谢谢,希望你们能帮我解决这个问题。现在我正在使用 Postman 对其进行测试,但稍后文件将通过表单发送。

【问题讨论】:

    标签: node.js reactjs amazon-web-services amazon-s3 react-router


    【解决方案1】:

    你可以为每个文件多次调用uploadFile:

    try{
        const promises= []
        for(const img of images) {
              promises.push(uploadFile(img))
            }
        await Promise.all(promises)
        //rest of logic
    
    }catch(err){ //handle err }
    

    顺便说一句,您应该在承诺中扭曲 S3.upload:

    const AWS = require('aws-sdk')
    
    const s3 = new AWS.S3({
      accessKeyId: process.env.AWS_ACCESS_KEY,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
    })
    
    module.exports = ({ params }) => {
      return new Promise((resolve, reject) => {
        s3.upload(params, function (s3Err, data) {
          if (s3Err) return reject(s3Err)
          console.log(`File uploaded successfully at ${data.Location}`)
          return resolve(data)
        })
      })
    }
    

    奖励,如果您希望避免让后端处理上传,您可以使用aws s3 signed urls 并让客户端浏览器处理,从而节省您的服务器资源。

    你的 Post 对象应该只包含媒体的 Urls 而不是媒体本身。

    【讨论】:

    • 您的代码向我抛出了“未定义图像”的错误。我尝试使用 const images = req.body.images 但没有用。
    • 代码仅供参考,我不知道您是如何将数据发送到服务器的。 req.body.images 应该是一个图像数组。 (我的猜测是您以 64 位编码二进制数据并发送它)。这可能会有所帮助,stackoverflow.com/questions/26805005/…
    【解决方案2】:
    // Setting up S3 upload parameters
        const params = {
            Bucket: bucket, // bucket name
            Key: fileName, // File name you want to save as in S3
            Body: Buffer.from(imageStr, 'binary'), //image must be in buffer
            ACL: 'public-read', // allow file to be read by anyone
            ContentType: 'image/png', // image header for browser to be able to render image
            CacheControl: 'max-age=31536000, public' // caching header for browser
        };
    
        // Uploading files to the bucket
        try {
            const result = await s3.upload(params).promise();
            return result.Location;
        } catch (err) {
            console.log('upload error', err);
            throw err;
        }
    

    【讨论】:

      猜你喜欢
      • 2015-03-17
      • 2018-12-20
      • 1970-01-01
      • 1970-01-01
      • 2013-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多