0
votes

I finished my (first and in real live) nodejs, express, handlebars project. Now, I can see the application on a "real" server, and also, real problems.

The application is very simple: users can post adds (like craiglist).

I was storing images with multer, in public/uploads, with only one requirement: just to be able to upload images (png, jpeg).

Problems come because people can upload images very heavy for server. I am looking for some solution but everything looks very complex for my actual knowledge. So, first question:

which way would you follow?

  • save images and after that compress in server side

or

  • before store through multer, resize and convert to lighter files (more ideas welcome)

I saw many modules as sharp, browser-image-compression, etc, but as I said this exceed my actual understanding.

Is any easier method to reach my target?

UPDATE:

this is my route file:

const express = require('express');
const router = express.Router();
const adsController = require('../controllers/ads.controller');
var multer  = require('multer')
var upload = multer({ dest: 'public/uploads', limits: { fileSize: 3000000 } });
const secure = require('../middleware/secure.mid');

...

router.post('/publicar-anuncio/:categoryId', upload.array('image'), adsController.doPost)

UPDATE 2:

// controller

    const {name, title, description, email } = req.body;
        const imageUpload = [];
        console.log(req.files)
        req.files.map(eachPath => imageUpload.push(`uploads/${eachPath.filename}`))

        const newMiscAd = new Misc ({name,title,description,email,image:{imgPath:imageUpload} })

....

User.findOne({email:email})
      .then(user => {
        if(user !== null){
          console.log(`User ${user.email} already exists`)
          newMiscAd.save()
          .then(ad => {
            User.updateOne({email:ad.email},{$push:{misc:ad._id}})
            .then(() => {
              createAdEmail({newAdEmail});

              res.render('ads/adSuccess')
            })            
          })
          .catch(error => {
            if (error instanceof mongoose.Error.ValidationError) {
              console.log(error)
              renderWithErrors(error.errors)
            } else {
                console.log('issue #userExist')
                next(error)
            }
          })
        } else {
          //new user through posting
          console.log(`User ${email} is new user MISC`)
          newMiscAd.save()
          .then(newAdData => {
            createAdEmail({newAdEmail});
            res.render('users/postSignup',{email:newAdData.email,id:newAdData._id,categoryAd:newAdData.category})
          })
          .catch(error => { 
// whatever
}
1

1 Answers

1
votes

multer actually gives this option to you. In backEnd side you can define size of image which will be uploaded by client and before saving it into database , you convert it to binary file type. It will also help you decrease size observably

Code UPDATE:

const multer = require('multer')
const sharp = require('sharp')
const router = new express.Router()

    var upload = multer({ 
        dest: 'public/uploads', 
        limits: { 
          fileSize: 3000000 } ,
        fileFilter(req, file, cb) {
        if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
            return cb(new Error('Please upload an image'))
        }
        cb(undefined, true)
    }
         });


router.post('/publicar-anuncio/:categoryId', upload.single('image'), async (req, res) => {
    const buffer = await sharp(req.file.buffer).resize({ width: 250, height: 250 }).png().toBuffer()
    req.user.avatar = buffer
    await req.user.save()
    res.status(201).send()
}, (error, req, res, next) => {
    res.status(400).send({ error: error.message })
})