本文介绍了如何在NodeJS中调用控制器内部的Multer中间件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试上载服务器中的图像。在前端,我使用的是ANGLE。前端工作正常,我张贴只是为了向您展示我是如何将文件传递到后端的!

Component.html

<div fxLayout="column" fxLayoutAlign="center center">
  <div>
    <mat-form-field>
      <ngx-mat-file-input placeholder="Only photos" [accept]="'.jpg, .jpeg, .png'" (change)="onChange($event)"></ngx-mat-file-input>
    </mat-form-field>
  </div>
  <div>
    <button mat-button (click)="onSubmit()">Send</button>
  </div>
</div>

Component.ts-函数

  imagem: File;

  constructor(private uploadService: UploadService) { }

  onChange(event) {
    this.imagem = event.target.files[0];
  }
  onSubmit() {
    this.uploadService.upload(this.imagem);
  }

pload.service.ts-函数

  constructor(private http: HttpClient) { }

  upload(file: File) {
    const formData = new FormData();
    formData.append('img', file, file.name);
    this.http.post(environment.apiBaseUrl + '/upload', formData, {responseType: 'text'}).subscribe(
      res => console.log('Done')
    );
  }

在后端,我有这样的结构:

app.js

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');

const rtsIndex = require('./routes/index.router');

var app = express();

// middleware
app.use(bodyParser.json());
app.use(cors());
app.use('/api', rtsIndex);

// start server
app.listen(3000, () => console.log('Port: 3000'));

index.router.js

const express = require('express');
const router = express.Router();

const ctrlUpload = require('../controllers/upload.controller');

router.post('/upload', ctrlUpload.send);

module.exports = router;

UPLAD.CONTROLER.js

const express = require('express');
const multer = require('multer');

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, 'uploads/');
    },
    filename: (req, file, cb) => {
        cb(null, Date.now()+'-'+file.originalname);
    }
});

const upload = multer({ storage });

module.exports.send = (req, res) => {
  upload.single('img');
  console.log(req.body, req.files);
  res.send('ok');
}

我试着调用了路由内部的中间件,但我认为这是不正确的,我没有达到目标。阿尔戈,上传的不是一个。在服务器端,我得到:{}未定义为结果,这可能意味着Multer没有处理该文件。在客户端,我得到的是:完成。

那么我做错了什么?我如何才能使它与这种后端结构一起工作?

推荐答案

Express中间件设计为安装在路由级别。事实上,在MVC模型中,Express程序员将控制器称为"路由"(我个人更倾向于将它们称为控制器,而不是我的代码中的路由)。从传统的MVC框架来看,将控制器与路由分离(它们的含义是相同的)并没有多大意义,但如果您愿意的话,您可以这样做。

要按设计使用multer,您需要在index.router.js中执行:

index.router.js

const express = require('express');
const router = express.Router();
const multer = require('multer');

const ctrlUpload = require('../controllers/upload.controller');

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, 'uploads/');
    },
    filename: (req, file, cb) => {
        cb(null, Date.now()+'-'+file.originalname);
    }
});

const upload = multer({ storage });

router.post('/upload', upload.single('img'), ctrlUpload.send);

module.exports = router;

然后您需要从upload.controller.js

中删除所有multer相关代码

但是,您可以在upload.controller.js中坚持这样做。这里的关键是要了解什么是中间件。

在Express中,中间件是带有原型的函数:

function (req, res, next) { // next is optional
    // middleware logic
}

是的,没错。upload.controller.js文件中的代码是中间件。您自己编写的中间件恰好位于中间件链的末端。

您看,Express只接受中间件。快递没有其他的东西。路由是碰巧在末端的中间件。

Express.use().get().post()和相关方法接受无限数量的参数。第一个参数是可选的路由说明符(但不是必需的),其余参数是中间件。例如:

app.get('/foo',
  (req, res, next) => {
    // first middleware
    next(); // next is what allows processing to continue
  },
  (req, res, next) => {
    // second middleware
    next();
  },
  (req, res, next) => {
    res.send('hello'); // controller logic - a controller
                       // is just the last middleware

    // Note: if you call next() instead of res.send() in a 
    // controller express will respond with a 500 internal 
    // server error status with whatever string you pass
    // to next() as the error message.
  }
);
了解了这一点,我们就知道函数upload.single('img')返回什么。该函数不执行中间件逻辑。相反,它返回中间件函数:

let middleware = upload.single('img');

// middleware is now a function with the prototype:
// (req, res, next) => {}

因此,要执行中间件逻辑,我们必须调用它(Express将自动调用它作为路由处理的一部分,就像它调用您的控制器函数一样,但如果我们想自己做这件事,我们可以)。

如果您想要在upload.controller.js中实现中间件,您需要做的是:

module.exports.send = (req, res, next) => {
  upload.single('img')(req, res, () => {
      // Remember, the middleware will call it's next function
      // so we can inject our controller manually as the next()

      console.log(req.body, req.files);
      res.send('ok');
  });
}

要拆开的东西太多了。如果我们稍微重构一下代码,就可以使代码更容易理解:

let middleware = upload.single('img');

module.exports.send = (req, res, next) => {
  // Define the controller here to capture
  // req and res in a closure:
  let controller = () => {
      console.log(req.body, req.files);
      res.send('ok');
  };

  middleware(req, res, controller); // call the middleware with
                                    // our controller as callback
}
但这是非常非标准的,对于经验丰富的Express.js程序员来说,这将是非常意想不到的。即使有可能,我也不会这么做。它还将中间件与您的控制器紧密耦合,完全否定了Express中间件配置系统的非常灵活的特性。

这篇关于如何在NodeJS中调用控制器内部的Multer中间件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-13 15:27