使用 multer-s3 nodejs 将图像上传到亚马逊 s3

Posted

技术标签:

【中文标题】使用 multer-s3 nodejs 将图像上传到亚马逊 s3【英文标题】:Uploading image to amazon s3 using multer-s3 nodejs 【发布时间】: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!");
);

为什么会出现这个错误?

【问题讨论】:

【参考方案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);
);

【讨论】:

您好,您能在这里看看我的问题吗,非常感谢您的帮助。***.com/questions/65479245/nodejs-multer-aws-s3 文件 URL 将在 req.file.location【参考方案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:只是想知道您是否能够解决您的问题。如果是,请将答案标记为已接受。

以上是关于使用 multer-s3 nodejs 将图像上传到亚马逊 s3的主要内容,如果未能解决你的问题,请参考以下文章

具有清晰上传和调整大小的 Multer-S3

上传图片 - Nodejs Paperclip 和 S3

使用 multer 和 nodejs 将图像上传到谷歌云存储时出错

使用 Nodejs、Express、Mongoose 和 React 将图像上传到 MongoDB

如何使用 multer 和 NodeJS 将图像上传到 GCS 存储桶?

如何在nodejs中使用sharp调整图像大小然后使用multer上传