问题描述
我正在尝试上载服务器中的图像。在前端,我使用的是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中间件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!