【问题标题】:When I send image file from PostMan, NodeJS multer has an error (req.file is undefined)当我从 PostMan 发送图像文件时,NodeJS multer 出现错误(req.file 未定义)
【发布时间】:2021-06-15 10:42:11
【问题描述】:

我最初尝试使用 multer-s3 将发送到服务器的图像文件保存为 s3。 但是,multer-s3 中间件的 req.file 或 req.files 一直返回 undefined。 所以,我放弃了 multer-s3 并尝试使用 multer 和 s3Client 保存图像,但它也失败了。 我使用multer的方式有问题吗?

框架是 express 的,正如我在标题中所说,我尝试使用 Postman 中的表单数据正文发送图像。另外,我尝试在邮递员的请求标头中未指定 Content-Type,但它是相同的。我在项目中写的代码如下。


./app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var bodyParser = require('body-parser');
var cors = require('cors');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var { sequelize } = require('./models');

var app = express();

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.set('port', process.env.PORT || 3000);

app.use(logger('dev'));
// app.use(express.json());
// app.use(express.urlencoded({ extended: false }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(cors());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

sequelize.sync({ force: false })
  .then(() => {
    console.log('connect to db');
  })
  .catch((err) => {
    console.error(err);
  });

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  res
    .status(404)
    .json({
      responseMsg: 'not correct http method or path',
    });
  // next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), 'waiting for client');
});

module.exports = app;


./routes/index.js

var express = require('express');
var router = express.Router();
var path = require('path');
var { upload } = require('../lib/upload');

var member = require("./member");
var admin = require("./admin");
var column = require("./column");

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express2' });
});

router.post('/uploadOne', upload.single('img'), (req, res) => {
    console.log(req.file);
    const image = req.file;
    if(image == undefined) {
        res
            .status(400)
            .json({
                responseMsg: 'no image'
            });
    } else {
        res
            .status(201)
            .json({
                responseMsg: 'success',
                file: req.file,
            });
    }
});

router.post("/admin/login", admin.isAdmin);
router.get("/admin/verify", admin.verifyToken);
router.post("/admin/body", admin.getBody);

router.use("/api/member", member);
router.use("/api/column", column);

module.exports = router;

./lib/upload.js

const multer = require('multer');
const multerS3 = require('multer-s3')
const AWS = require("aws-sdk");
require('dotenv').config();

AWS.config.update({
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    region: process.env.AWS_S3_REGION
});

const s3 = new AWS.S3();

let upload = multer({
    storage: multerS3({
        s3: s3,
        bucket: '************',
        contentType: multerS3.AUTO_CONTENT_TYPE, 
        acl: 'public-read-write',
        metadata: function (req, file, cb) {
            cb(null, {fieldName: file.fieldname});
        },
        key: (req, file, cb) => { 
            console.log("success???? " + file);
            cb(null, 'users/' + file.originalname);
        },
    }),
    limits: { fileSize: 12 * 1024 * 1024 },
});

exports.upload = upload;

package.json 依赖项

"dependencies": {
    "aws-sdk": "^2.865.0",
    "body-parser": "^1.19.0",
    "connect-multiparty": "^2.2.0",
    "cookie-parser": "~1.4.4",
    "cors": "^2.8.5",
    "debug": "~2.6.9",
    "dotenv": "^8.2.0",
    "ejs": "~2.6.1",
    "express": "~4.16.1",
    "http-errors": "~1.6.3",
    "jsonwebtoken": "^8.5.1",
    "morgan": "~1.9.1",
    "multer": "^1.4.2",
    "multer-s3": "^2.9.0",
    "multer-s3-transform": "^2.10.3",
    "mysql2": "^2.2.5",
    "sequelize": "^6.3.5",
    "sequelize-cli": "^6.2.0",
    "sharp": "^0.27.2"
  },
  "devDependencies": {
    "nodemon": "^2.0.6"
  }

【问题讨论】:

  • 所以你想使用multer获取本地保存的文件,然后使用SDK上传到amazon S3?
  • 任何一种方式都可以。无论是使用 Multer 模块将发送给 postman 的图像文件保存到本地还是 s3,我都想成功。 @Darkripper

标签: javascript node.js express multer-s3


【解决方案1】:

有两种方法可以做到这一点,您可以只使用multermulter-s3

为简单起见,我将向您展示仅使用 multer 的方式。

处理流程如下:

  1. Multer 进程并保存到本地
  2. 您从本地读取,并使用 s3 SDK 上传到 s3
    // Make "temp" directory as multer.diskStorage wont create folder
    fs.mkdir('./temp', { recursive: true }, (err) => {
      if (err) throw err;
    });
    const PORT = parseInt(process.argv[2]) || parseInt(process.env.PORT) || 3000;
    // Multer
    const storage = multer.diskStorage({
      destination: function (req, file, cb) {
        cb(null, './temp');
      },
      filename: function (req, file, cb) {
        let extArray = file.mimetype.split('/');
        let extension = extArray[extArray.length - 1];
        cb(null, new Date().getTime() + '.' + extension);
      },
    });
    
    const upload = multer({ storage: storage });
    
    const endpoint = new AWS.Endpoint(AWS_S3_HOSTNAME);
    const s3 = new AWS.S3({
      endpoint,
      accessKeyId: AWS_S3_ACCESSKEY_ID,
      secretAccessKey: AWS_S3_SECRET_ACCESSKEY,
    });
    
    // Get the uploaded file in local here
    const readFile = (path) =>
      new Promise((resolve, reject) =>
        fs.readFile(path, (err, buff) => {
          if (null != err) reject(err);
          else resolve(buff);
        })
    
    // Upload to AWS S3 here
    const putObject = (file, buff, s3) =>
      new Promise((resolve, reject) => {
        const params = {
          Bucket: AWS_S3_BUCKET_NAME,
          Key: file.filename,
          Body: buff,
          ACL: 'public-read',
          ContentType: file.mimetype,
          ContentLength: file.size,
        };
        s3.putObject(params, (err, result) => {
          if (null != err) reject(err);
          else resolve(file.filename);
        });
      });
      );
    
    app.post('/api/post', upload.single('imageFile'), async (req, res) => {
    readFile(req.file.path)
            .then((buff) =>
              // Insert Image to S3 upon succesful read
              putObject(req.file, buff, s3)
            )
            .then((results) => {
              // build url of the resource upon successful insertion
              const resourceURL = `https://${AWS_S3_BUCKET_NAME}.${AWS_S3_HOSTNAME}/${results}`;
              const doc = {
                comments,
                title,
                ts: new Date(),
                image: resourceURL, // Your URL reference to image here
              };
            res.status(200).json(doc)
            })
            .catch((error) => {
              console.error('insert error: ', error);
              res.status(500);
              res.json({ error });
            });
}

【讨论】:

    猜你喜欢
    • 2022-01-18
    • 2020-12-17
    • 1970-01-01
    • 2019-03-31
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 2020-07-19
    相关资源
    最近更新 更多