Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
374 views
in Technique[技术] by (71.8m points)

javascript - nodejs, multer, aws S3

How do i apply uuid and date so that the filename stored in my database and the filename stored in my S3 bucket are the same?

With this current implementation, the uuid and the date are always the same even if a post was made hours later.

Can someone help, would really appreciate it.

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 },
});

Here is my post request

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())

With this current implementation the the files are getting stored in both the db and s3.

Also, another question i have is what is the difference between using multer and multer-s3? I tried using multer to post the images to s3 but it did not work so i used multer-s3 and it worked.

UPDATE

 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 },
});

Here is my post request

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())

My problem is the date and uuid variables both will initialize when node server start, it never changes until your node server restarts

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Quick fixes:

  • remain same
const s3 = new AWS.S3({
    accessKeyId: process.env.AWS_ID,
    secretAccessKey: process.env.AWS_SECRET,
    region: process.env.AWS_REGION
});
  • the date and uuid variables both will initialize when node server start, it will never change until your node server restart, you just need to put it in to a function to return every time new file name,
  • here function returns filename except extension
function getFilename() {
    return new Date().toISOString() + '-' + uuidv4();
}
  • create function for transforms and pass same filename in both version from getFilename() function, add filename in metadata as well,
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"
            });
        }
    }
}
  • call getTransforms() function, that will return transforms and matadata properties
  • i am not sure aboutyour login to store filename in database,
  • get name from transfoems.metadata that we passed from metadata, this will return only _full name,
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]
        })
    });
    
})

Basically the statement multer-s3 Streaming multer storage engine for AWS S3. is enough to differentiate both multer and multer-s3.

The code has not been tested, you can workaround and see what's happen!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...