【问题标题】:express.js: pass an uploaded image to s3express.js:将上传的图像传递给 s3
【发布时间】:2021-10-15 11:23:47
【问题描述】:

我正在尝试将从 react 应用程序通过 express 上传的图像传递到托管 s3 存储桶。我使用的平台/主机创建和管理 s3 存储桶并生成上传和访问 url。这一切都很好(我已经在 postman 中测试了一个生成的上传 url,其中包含二进制正文中的图像,并且效果很好)。

我的问题是通过快递传递图像。我正在使用 multer 从表单中获取图像,但我假设 multer 正在将该图像转换为某种文件对象,而 s3 期待某种 blob 或流。

在以下代码中,req.file 中的图像存在,我从 s3 收到 200 响应,没有错误,当我访问资产 url 时,该 url 有效,但图像本身丢失。

const router = Router();
const upload = multer()

router.post('/', upload.single('file'), async (req, res) => {
    console.log(req.file)
    const asset = req.file
    const assetPath = req.headers['asset-path']

    let s3URLs = await getPresignedURLS(assetPath)
  
    const sendAsset = await fetch(
      s3URLs.urls[0].upload_url, // the s3 upload url 
      {
        method: 'PUT',
        headers: {
            "Content-Type": asset.mimetype
        },
        body: asset,
        redirect: 'follow'
      }
    )
  console.log("s3 response", sendAsset)

  res.status(200).json({"url": s3URLs.urls[0].access_url });
  
});

export default router;

我不确定如何将 multer 给我的内容转换为 aws s3 可以接受的内容。如果有更简单的方法可以上传二进制文件来表达,我也愿意摆脱 multer。

【问题讨论】:

  • 你试过 multer-s3 npmjs.com/package/multer-s3 吗?
  • 我无权访问 s3 存储桶,因为我从未创建它,只有一个上传 url 和一个访问 url。

标签: javascript node.js express amazon-s3 multer


【解决方案1】:

您可以使用multiparty 代替multer 从请求对象获取文件数据。要将文件上传到 s3 存储桶,您可以使用aws-sdk

const AWS = require("aws-sdk");
const multiparty = require("multiparty");

/**
 * Helper method which takes the request object and returns a promise with a data.
 */
const getDataFromRequest = (req) =>
  new Promise(async(resolve, reject) => {
    const form = new multiparty.Form();
    await form.parse(req, (err, fields, files) => {
      if (err) reject(err);
      const bucketname = fields.bucketname[0];
      const subfoldername = fields.subfoldername[0];
      const file = files["file"][0]; // get the file from the returned files object
      if (!file) reject("File was not found in form data.");
      else resolve({
        file,
        bucketname,
        subfoldername
      });
    });
  });

/**
 * Helper method which takes the request object and returns a promise with the AWS S3 object details.
 */
const uploadFileToS3Bucket = (
  file,
  bucketname,
  subfoldername,
  options = {}
) => {
  const s3 = new AWS.S3();

  // turn the file into a buffer for uploading
  const buffer = readFileSync(file.path);

  var originalname = file.originalFilename;
  var attach_split = originalname.split(".");
  var name = attach_split[0];
  // generate a new random file name
  const fileName = name;

  // the extension of your file
  const extension = extname(file.path);

  console.log(`${fileName}${extension}`);

  const params = {
    Bucket: bucketname, //Bucketname
    ACL: "private", //Permission
    Key: join(`${subfoldername}/`, `${fileName}${extension}`), // File name you want to save as in S3
    Body: buffer, // Content of file
  };

  // return a promise
  return new Promise((resolve, reject) => {
    return s3.upload(params, (err, result) => {
      if (err) reject(err);
      else resolve(result); // return the values of the successful AWS S3 request
    });
  });
};

router.post('/', upload.single('file'), async(req, res) => {
  try {
    // extract the file from the request object
    const {
      file,
      bucketname,
      subfoldername
    } = await getDataFromRequest(req);

    // Upload File to specified bucket
    const {
      Location,
      ETag,
      Bucket,
      Key
    } = await uploadFileToS3Bucket(
      file,
      bucketname,
      subfoldername
    );

    let response = {};
    res["Location"] = Location;
    response["ETag"] = ETag;
    response["Bucket"] = Bucket;
    response["Key"] = Key;

    res.status(200).json(response);
  } catch (error) {
    throw error;
  }

});

请求正文将是具有以下字段的表单数据

  1. 存储桶名称:
  2. 子文件夹名:
  3. 文件:文件数据

【讨论】:

    【解决方案2】:

    对于任何偶然发现这个问题的人,解决方案是创建一个custom multer storage engine。在引擎内部,您可以使用 s3 接受的流属性(使用正确的标头)访问文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多