Как вызвать многоуровневое промежуточное ПО внутри контроллера в nodejs? - PullRequest
0 голосов
/ 20 октября 2019

Я пытаюсь загрузить изображение на свой сервер. В front-end я работаю с Angular. Внешний интерфейс работает нормально, я только написал, чтобы показать вам, как я передаю файл на сервер!

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

upload.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;

upload.controller.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');
}

Я пытался вызвать промежуточное ПО внутри маршрутизации, но я не думаю, что это правильно, и я не достиг цели,Альго, загрузка не одна. На стороне сервера я получаю: {} undefined как результат, что, вероятно, означает, что multer не обрабатывает файл. На стороне клиента я получаю: Готово.

Так что я делаю не так? И как я могу заставить это работать с этой структурой конца?

1 Ответ

0 голосов
/ 20 октября 2019

Express промежуточное программное обеспечение предназначено для установки на уровне маршрутизации. Действительно, в модели MVC экспресс-программисты называют контроллеры «маршрутами» (лично я переименую их в контроллеры вместо маршрутов в моем коде). Отделение контроллеров от маршрутов (оба они означают одно и то же) не имеет особого смысла, если смотреть на них из традиционных сред 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;

Затем вам нужно удалить всеmulter связанный код от upload.controller.js


Однако вы можете настаивать на этом в 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...