Uploading image to amazon s3 using multer-s3 nodejs

前端 未结 6 1899
遥遥无期
遥遥无期 2020-12-04 15:45

I am trying to upload an image to amazon s3 using multer-s3, but I am getting this error:

TypeError: Expected opts.s3 to be object node

相关标签:
6条回答
  • 2020-12-04 16:35

    I was passing S3 to mutler in caps, like

    S3: {object}
    

    Changing it to small s3 works for me:-

    s3: {object}
    
    0 讨论(0)
  • 2020-12-04 16:36

    @V31 has answered very well still I want to add my 2 cents.

    I believe in keeping one responsibility into one file, for better code organization and debugging purpose.

    I have created a file for uploading upload.js.

    require('dotenv').config();
    const AWS = require('aws-sdk');
    const multer = require('multer');
    const multerS3 = require('multer-s3');
    
    const s3Config = new AWS.S3({
        accessKeyId: process.env.AWS_IAM_USER_KEY,
        secretAccessKey: process.env.AWS_IAM_USER_SECRET,
        Bucket: process.env.AWS_BUCKET_NAME
      });
    
    const fileFilter = (req, file, cb) => {
        if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
            cb(null, true)
        } else {
            cb(null, false)
        }
    }
    
    // this is just to test locally if multer is working fine.
    const storage = multer.diskStorage({
        destination: (req, res, cb) => {
            cb(null, 'src/api/media/profiles')
        },
        filename: (req, file, cb) => {
            cb(null, new Date().toISOString() + '-' + file.originalname)
        }
    })
    
    const multerS3Config = multerS3({
        s3: s3Config,
        bucket: process.env.AWS_BUCKET_NAME,
        metadata: function (req, file, cb) {
            cb(null, { fieldName: file.fieldname });
        },
        key: function (req, file, cb) {
            console.log(file)
            cb(null, new Date().toISOString() + '-' + file.originalname)
        }
    });
    
    const upload = multer({
        storage: multerS3Config,
        fileFilter: fileFilter,
        limits: {
            fileSize: 1024 * 1024 * 5 // we are allowing only 5 MB files
        }
    })
    
    exports.profileImage = upload; 
    

    Which is imported inside my routes routes.js

    const express = require('express');
    
    const ProfileController = require('../profile/controller');
    const { profileImage } = require('../utils/upload.js'); 
    
     const routes = (app) => {
        const apiRoutes = express.Router();
    
        apiRoutes.use('/profile', profileRoutes);
        profileRoutes.post('/',profileImage.single('profileImage'), ProfileController.saveProfile);
    
        app.use('/api', apiRoutes);
    
     }
    
    module.exports = routes
    

    Postman screen shot for post body

    0 讨论(0)
  • 2020-12-04 16:36

    I just want to add my cents,

    There are many comments in all answers like how to get public URL after uploading and S3 response object and lets see implementation and cases,

    // INITIALIZE NPMS
    var AWS = require('aws-sdk'),
    multer = require('multer'),
    multerS3 = require('multer-s3'),
    path = require('path');
    
    // CONFIGURATION OF S3
    AWS.config.update({
        secretAccessKey: '***********************************',
        accessKeyId: '****************',
        region: 'us-east-1'
    });
    
    // CREATE OBJECT FOR S3
    const S3 = new AWS.S3();
    
    // CREATE MULTER FUNCTION FOR UPLOAD
    var upload = multer({
        // CREATE MULTER-S3 FUNCTION FOR STORAGE
        storage: multerS3({
            s3: S3,
            acl: 'public-read',
            // bucket - WE CAN PASS SUB FOLDER NAME ALSO LIKE 'bucket-name/sub-folder1'
            bucket: 'bucket-name',
            // META DATA FOR PUTTING FIELD NAME
            metadata: function (req, file, cb) {
                cb(null, { fieldName: file.fieldname });
            },
            // SET / MODIFY ORIGINAL FILE NAME
            key: function (req, file, cb) {
                cb(null, file.originalname); //set unique file name if you wise using Date.toISOString()
                // EXAMPLE 1
                // cb(null, Date.now() + '-' + file.originalname);
                // EXAMPLE 2
                // cb(null, new Date().toISOString() + '-' + file.originalname);
    
            }
        }),
        // SET DEFAULT FILE SIZE UPLOAD LIMIT
        limits: { fileSize: 1024 * 1024 * 50 }, // 50MB
        // FILTER OPTIONS LIKE VALIDATING FILE EXTENSION
        fileFilter: function(req, file, cb) {
            const filetypes = /jpeg|jpg|png/;
            const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
            const mimetype = filetypes.test(file.mimetype);
            if (mimetype && extname) {
                return cb(null, true);
            } else {
                cb("Error: Allow images only of extensions jpeg|jpg|png !");
            }
        }
    });
    

    There are three cases, if we want to retrieve files res object from S3 after upload:

    Case 1: When we are using .single(fieldname) method it will return file object in req.file

    app.post('/upload', upload.single('file'), function (req, res, next) {
        console.log('Uploaded!');
        res.send(req.file);
    });
    

    Case 2: When we are using .array(fieldname[, maxCount]) method it will return file object in req.files

    app.post('/upload', upload.array('file', 1), function (req, res, next) {
        console.log('Uploaded!');
        res.send(req.files);
    });
    

    Case 3: When we are using .fields(fields) method it will return file object in req.files

    app.post('/upload', upload.fields([
      { name: 'avatar', maxCount: 1 },
      { name: 'gallery', maxCount: 8 }
    ]), function (req, res, next) {
        console.log('Uploaded!');
        res.send(req.files);
    });
    
    0 讨论(0)
  • 2020-12-04 16:38

    /*** Using Multer To Upload Image image is uploading */

    const fileStorage = multer.diskStorage({
      destination: function(req, file, cb) {
        cb(null, "./public/uploads");
      },
      filename: function(req, file, cb) {
        cb(null, file.originalname);
      }
    });
    
    /** AWS catalog */
    
    aws.config.update({
      secretAccessKey: process.env.SECRET_KEY,
      accessKeyId: process.env.ACCESS_KEY,
      region: "us-east-1"
    });
    
    const s3 = new aws.S3();
    const awsStorage = multerS3({
      s3: s3,
      bucket: process.env.BUCKET_NAME,
      key: function(req, file, cb) {
        console.log(file);
        cb(null, file.originalname);
      }
    });
    
    const upload = multer({
      storage: awsStorage(),
      /** in above line if you are using local storage in ./public/uploads folder than use
       ******* storage: fileStorage,
       * if you are using aws s3 bucket storage than use
       ******* storage: awsStorage(),
       */
      limits: { fileSize: 5000000 },
      fileFilter: function(req, file, cb) {
        checkFileType(file, cb);
      }
    });
    app.post("/user-profile-image", upload.single("profile"), (req, res, err) => {
      try {
        res.send(req.file);
      } catch (err) {
        res.send(400);
      }
    });
    
    const checkFileType = (file, cb) => {
      const filetypes = /jpeg|jpg|png|gif/;
      const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
      const mimetype = filetypes.test(file.mimetype);
    
      if (mimetype && extname) {
        return cb(null, true);
      } else {
        cb("Error: Images Only!");
      }
    };
    
    0 讨论(0)
  • 2020-12-04 16:43

    Complete and working Node Cheat | Upload to s3 using multer-s3 available.

    Code:

    var express = require('express'),
        aws = require('aws-sdk'),
        bodyParser = require('body-parser'),
        multer = require('multer'),
        multerS3 = require('multer-s3');
    
    aws.config.update({
        secretAccessKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
        accessKeyId: 'XXXXXXXXXXXXXXX',
        region: 'us-east-1'
    });
    
    var app = express(),
        s3 = new aws.S3();
    
    app.use(bodyParser.json());
    
    var upload = multer({
        storage: multerS3({
            s3: s3,
            bucket: 'bucket-name',
            key: function (req, file, cb) {
                console.log(file);
                cb(null, file.originalname); //use Date.now() for unique file keys
            }
        })
    });
    
    //open in browser to see upload form
    app.get('/', function (req, res) {
        res.sendFile(__dirname + '/index.html');//index.html is inside node-cheat
    });
    
    //use by upload form
    app.post('/upload', upload.array('upl',1), function (req, res, next) {
        res.send("Uploaded!");
    });
    
    app.listen(3000, function () {
        console.log('Example app listening on port 3000!');
    });
    

    For complete repo:

    Clone node-cheat express_multer_s3, run node app followed by npm install express body-parser aws-sdk multer multer-s3.

    Happy Helping!

    0 讨论(0)
  • 2020-12-04 16:45

    s3 needs to be an object to be passed. According to the docs, the object needs to be like this:

    var upload = multer({
      storage: multerS3({
        s3: s3,
        bucket: 'some-bucket',
        metadata: function (req, file, cb) {
          cb(null, {fieldName: file.fieldname});
        },
        key: function (req, file, cb) {
          cb(null, Date.now().toString())
        }
      })
    })
    

    MulterS3 Docs

    0 讨论(0)
提交回复
热议问题