【问题标题】:Uploading image to amazon s3 using multer-s3 nodejs使用 multer-s3 nodejs 将图像上传到亚马逊 s3
【发布时间】:2017-03-22 12:01:03
【问题描述】:

我正在尝试使用 multer-s3 将图像上传到 amazon s3,但出现此错误:

TypeError:预期 opts.s3 为对象 node_modules/multer-s3/index.js:69:20

这是我的服务器代码:

var upload = multer({
    storage: s3({
        dirname: '/',
        bucket: 'bucket',
        secretAccessKey: 'key',
        accessKeyId: 'key',
        region: 'us-west-2',
        filename: function (req, file, cb) {
            cb(null, file.originalname); 
        }
    })
});

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

为什么会出现这个错误?

【问题讨论】:

    标签: node.js file-upload amazon-s3 multer multer-s3


    【解决方案1】:
        //here is the function for upload the images on aws bucket using multer
        
        const path = require('path');
        const fs = require('fs');
        const aws = require('aws-sdk');
        const multer = require('multer');
        const multerS3 = require('multer-s3');
        
        
        aws.config.update({
            secretAccessKey: '**************************',
            accessKeyId: '********************',
            region: '**********************'
        });
        
        s3 = new aws.S3();
        
        
        const storage = multerS3({
            s3: s3,
            bucket: 'bucket-name',
            key: function(req, file, cb) {
                console.log(file);
                cb(null, file.originalname);
            }
        })
        
        //export the created function
        exports.uploadVideo = multer({ storage: storage }).single('file_name');
        
     //================================================================================   
        
        //import uploadVideo function whenever you need to upload the file on aws s3 bucket
        const { uploadVideo } = require('../../services/upload');
        
        exports.videoUpload = (req, res) => {
            uploadVideo(req, res, function(err) {
                if (err) {
                    console.log(err);
                    res.json({ status: 401, msg: err.message });
                } else {
                    const image = getImagePath(req.file.filename);
                    res.json({ status: 200, msg: 'Image uploaded sucess.', data: image });
                }
            });
        }
        //================================================================================
        
        //here is route file
        router.post('/video-upload',uploadController.videoUpload);
    

    【讨论】:

      【解决方案2】:

      我只想加分,

      上传后如何获取公共 URLS3 响应对象等所有答案中都有很多 cmets,让我们看看实现和案例,

      // 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 !");
              }
          }
      });
      

      分三种情况,如果我们想上传后从S3中获取文件res对象

      案例1:当我们使用.single(fieldname)方法时,它会在req.file

      中返回文件对象
      app.post('/upload', upload.single('file'), function (req, res, next) {
          console.log('Uploaded!');
          res.send(req.file);
      });
      

      案例 2: 当我们使用 .array(fieldname[, maxCount]) 方法时,它会在 req.files

      中返回文件对象
      app.post('/upload', upload.array('file', 1), function (req, res, next) {
          console.log('Uploaded!');
          res.send(req.files);
      });
      

      案例 3: 当我们使用 .fields(fields) 方法时,它会在 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);
      });
      

      【讨论】:

      【解决方案3】:

      我正在将 S3 传递给大写字母 mutler,比如

      S3: {object}
      

      将其更改为小型 s3 对我有用:-

      s3: {object}
      

      【讨论】:

        【解决方案4】:

        /*** Using Multer To Upload Image 图片正在上传 */

        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!");
          }
        };
        

        【讨论】:

        • 欢迎来到 SO :) 请编辑您的答案以解释您的代码如何解决 OP 面临的问题。
        【解决方案5】:

        @V31 回答得很好,我还想加我的 2 美分。

        我相信将一项职责保存到一个文件中,以实现更好的代码组织和调试目的。

        我创建了一个文件用于上传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; 
        

        在我的路由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
        

        帖子正文的邮递员屏幕截图

        【讨论】:

        • 能否请您发布必须从 Angular 前端或邮递员客户端调用的请求和正文的详细信息?
        • @Satyam 请查看 Postman 中帖子正文的附件截图
        • 下一个编辑可能是 :) @Anjum.... 回答得很好,但我想加我的 2 美分。
        【解决方案6】:

        完成并可以使用Node Cheat | Upload to s3 using multer-s3

        代码:

        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!');
        });
        

        完整的回购

        克隆节点作弊express_multer_s3,运行node app,然后运行npm install express body-parser aws-sdk multer multer-s3

        乐于助人!

        【讨论】:

        • 为什么这个答案没有一百万个赞?这对我有帮助。谢谢。您可能需要更新:aws.config.update({ signatureVersion: 'v4',,因为我遇到了一个错误并且这样做解决了它。
        • 真的很有帮助。
        • 对我来说,同一行代码显示此错误"error":{"errno":-4058,"syscall":"open","code":"ENOENT","path":"undefined/undefined"}
        • 我们如何获取上传文件的 s3 url。
        • 我尝试了这段代码,我得到了一个类似“错误:多部分数据意外结束”的错误,我不知道为什么我这几天一直在寻找解决方案,请帮助我
        【解决方案7】:

        s3 需要是要传递的对象。根据文档,对象需要是这样的:

        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

        【讨论】:

        • 上面的accesskeyId在哪里提供
        • @mBlaze:您需要使用 aws sdk 使用 var s3 = new aws.S3({ /* ... */ }) 创建一个 s3 对象。您可以使用链接docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/… 找到更多信息
        • @mBlaze:只是想知道您是否能够解决您的问题。如果是,请将答案标记为已接受。
        猜你喜欢
        • 2012-07-07
        • 2017-08-01
        • 2016-01-11
        • 1970-01-01
        • 1970-01-01
        • 2015-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多