nodejs、multer、aws S3

IT技术 javascript node.js amazon-s3 uuid multer-s3
2021-03-13 21:55:28

我如何应用 uuid 和 date 以便存储在我的数据库中的文件名和存储在我的 S3 存储桶中的文件名相同?

使用当前的实现,即使帖子是在几个小时后发布的,uuid 和日期也始终相同。

有人可以帮忙吗,真的很感激。

const s3 = new AWS.S3({
 accessKeyId: process.env.AWS_ID,
 secretAccessKey: process.env.AWS_SECRET,
 region:process.env.AWS_REGION
 })

const uid =uuidv4();
const date =new Date().toISOString()

const multerS3Config = multerS3({
      s3: s3,
      bucket: process.env.AWS_BUCKET,
      metadata: function (req, file, cb) {
               cb(null, { fieldName: file.fieldname }); },
      shouldTransform: true,
      acl: 'public-read',
      contentType: multerS3.AUTO_CONTENT_TYPE,
      transforms: [
                  {
                    id: 'full',
                    key: (req, file, cb) => cb(null, file.originalname 
                         + "-"  + `${date}` + "-" + `${uid}` + 
                         "_full.jpg"),
                    transform: (req, file, cb) => cb(null, 
                               sharp().resize(2000).jpeg({ 
                               quality: 50 }))
                   },
                   {
                     id: 'thumb',
                     key: (req, file, cb) => cb(null, 
                          file.originalname + "-"  + 
                          `${date}` + "-" + `${uid}` + "_thumb.jpg"),
                     transform: (req, file, cb) => cb(null, 
                                sharp().resize(100).jpeg({ 
                                quality: 30 }))
                   },
                   ],
                });

const upload = multer({
storage: multerS3Config,
limits: { fieldSize: 25 * 1024 * 1024 },
});

这是我的帖子请求

router.post(
"/",
 [    upload.array("images", config.get("maxImageCount"))],
 async (req, res) => {
const paths = await req.files.map((file) => ({ originalName: file.originalname + "-" + 
`${date}` 
+ "-" + `${uid}`}));
await Post.create({
title: req.body.title,
userId: req.body.userId,
Post_Images: paths.map((x) => ({ images: x.originalName })),
},
{ 
include: [Post_Image] }).then(
res.status(201).send())

通过当前的实现,文件将同时存储在 db 和 s3 中。

另外,我的另一个问题是使用 multer 和 multer-s3 之间有什么区别?我尝试使用 multer 将图像发布到 s3 但它不起作用所以我使用了 multer-s3 并且它起作用了。

更新

 const s3 = new AWS.S3({
 accessKeyId: process.env.AWS_ID,
 secretAccessKey: process.env.AWS_SECRET,
 region:process.env.AWS_REGION
 })

function getFilename() {
return new Date().toISOString() + '-' + uuidv4();
}

function getTransforms() {
const fileName = getFilename();
return {
transforms:[
  {
      id: 'full',
      key: (req, file, cb) => {
        let fname = file.originalname.split(".");
        cb(null, fname[0] + '-' + fileName + "_full.jpg")},
      transform: (req, file, cb) => cb(null,
          sharp().resize(2000).jpeg({
              quality: 50
          }))
  },
  {
      id: 'thumb',
      key: (req, file, cb) => {
        let fname = file.originalname.split(".");
        cb(null, fname[0] + '-' + fileName + "_thumb.jpg")},
      transform: (req, file, cb) => cb(null,
          sharp().resize(100).jpeg({
              quality: 30
          }))
  }
  ],
metadata: (req, file, cb) => {
let fname = file.originalname.split(".");
cb(null, { 
    fieldName: file.fieldname, 
    key: fname[0] + '-' + fileName
});
}}}

const multerS3Config = multerS3({
      s3: s3,
      bucket: process.env.AWS_BUCKET,
      shouldTransform: true,
      acl: 'public-read',
      contentType: multerS3.AUTO_CONTENT_TYPE,
      ...getTransforms()
      });

const upload = multer({
storage: multerS3Config,
limits: { fieldSize: 25 * 1024 * 1024 },
});

这是我的帖子请求

router.post(
"/",
 [    upload.array("images", config.get("maxImageCount"))],
 async (req, res) => {

const paths = await req.files.map((file) => ({ images: 
              file.transforms[0].metadata.key}));

await Post.create({
title: req.body.title,
userId: req.body.userId,
Post_Images: paths,
},
{ 
include: [Post_Image] }).then(
res.status(201).send())

我的问题是 the date and uuid variables both will initialize when node server start, it never changes until your node server restarts

1个回答

快速修复:

  • 保持不变
const s3 = new AWS.S3({
    accessKeyId: process.env.AWS_ID,
    secretAccessKey: process.env.AWS_SECRET,
    region: process.env.AWS_REGION
});
  • dateuuid变量都将初始化时,节点服务器启动,它永远不会改变,直到您的节点服务器重启,你只需把它放在一个函数返回每一次新的文件名,
  • here 函数返回除扩展名之外的文件名
function getFilename() {
    return new Date().toISOString() + '-' + uuidv4();
}
  • 为转换创建函数并在getFilename()函数的两个版本中传递相同的文件名,也在元数据中添加文件名,
function getTransforms() {
    const fileName = getFilename();
    return {
        transforms: [
            {
                id: "full",
                key: (req, file, cb) => {
                    let fname = file.originalname.split(".")
                    cb(null, fname[0] + '-' + fileName + "_full.jpg")
                },
                transform: (req, file, cb) => cb(null, sharp().resize(2000).jpeg({ quality: 50 }))
            },
            {
                id: "thumb",
                key: (req, file, cb) => {
                    let fname = file.originalname.split(".")
                    cb(null, fname[0] + '-' + fileName + "_thumb.jpg")
                },
                transform: (req, file, cb) => cb(null, sharp().resize(100).jpeg({ quality: 30 }))
            }
        ],
        metadata: (req, file, cb) => {
            let fname = file.originalname.split(".");
            cb(null, { 
                fieldName: file.fieldname, 
                key: fname[0] + '-' + fileName + ".jpg"
            });
        }
    }
}
  • 调用getTransforms()函数,它将返回转换和 matadata 属性
  • 我不确定您的登录名以将文件名存储在数据库中,
  • transfoems.metadata我们从元数据传递的名称中获取名称,这将仅返回 _full 名称,
router.post("/", async (req, res) => {

    const multerS3Config = multerS3({
        s3: s3,
        bucket: process.env.AWS_BUCKET,
        shouldTransform: true,
        acl: 'public-read',
        contentType: multerS3.AUTO_CONTENT_TYPE,
        ...getTransforms()
    });

    const upload = multer({
        storage: multerS3Config,
        limits: { fieldSize: 25 * 1024 * 1024 }
    });

    upload.array("images", config.get("maxImageCount"))(req, res, async(error) => {
        const paths = await req.files.map((file) => ({
            images: file.transforms[0].metadata.key
        }));
        await Post.create({
            title: req.body.title,
            userId: req.body.userId,
            Post_Images: paths,
        }, {
            include: [Post_Image]
        })
    });
    
})

基本上声明multer-s3 用于 AWS S3 的 Streaming multer 存储引擎。足以区分multer和multer-s3。

该代码尚未经过测试,您可以解决此问题,看看会发生什么!

@Pogridis 是的,但它不起作用。我只希望上传到数据库和 s3 的每个文件的 uuid 和日期都相同。
2021-04-17 21:55:28
kd,一旦它被编码,它就会有一个 uid,要记录它,你需要递归地字符串化对象。你测试过/调试过吗?
2021-04-22 21:55:28
@turivishal 它有效 :) 你的传奇,非常感谢你,我非常感谢你的帮助。希望你有一个美好的一天
2021-05-01 21:55:28