使用 React.js、Node.js 和 Multer,如何在服务器上控制日志 'req.file'?

Using React.js, Node.js and Multer, how can I console log 'req.file' on the server?

我正在构建一个 MERN 应用程序,当我尝试在服务器上 console.log(req.file) 时,我得到了未定义。我检查了 multer github 页面和其他 SO 文章,但我仍然无法使用 React hooks 和 jsx 弄清楚。我是 SO 的新手,所以我会添加编辑,因为我还不能发表评论。

如果您想查看所有文件,请点击 link 到 GitHub 中的分支。 https://github.com/BenjDG/puzzle-gallery/tree/so

我是 multer 和 react 的新手,非常感谢您的帮助。

这是我的代码:

server\controllers\puzzleController.js

const multer = require('multer');
const upload = multer({ dest: './uploads'});
const db = require('../models');
const fs = require('fs');

const type = upload.single('picFile');

// Defining methods for the puzzleController
module.exports = {
  findAll: function (req, res) {
    db.Puzzle
      .find(req.query)
      .then(dbModel => res.json(dbModel))
      .catch(err => res.status(422).json(err));
  },
  save: (type, function (req, res) {
    // console.log(req);
    console.log(req.file);
    console.log(req.body);
    res.sendStatus(200);
  }),
  remove: function (req, res) {
    db.Puzzle
      .findById({ _id: req.params.id })
      .then(dbModel => dbModel.remove())
      .then(dbModel => res.json(dbModel))
      .catch(err => res.status(422).json(err));
  }
};

client\src\components\gallery\index.js

import React, { useState } from 'react';
import './styles.css';
import API from '../../services/API';


export default function Gallery () {
  const [picFile, setPicFile] = useState();

  const handleGetClick = async () => {
    API.findAll()
      .then(res => {
        console.log(res)
      })
      .catch(err => console.error(err))
  }

  const handleUploadClick = async (e) => {
    e.preventDefault();
    // console.log(picFile);

    // create new formData instance
    const bodyFormData = new FormData();

    // append single file to formData instance
    bodyFormData.append('picFile', picFile.selectedFile);

    // log items in formData object
    for (const element of bodyFormData) {
      console.log(element);
    }

    // send formData obj to axios function
    API.save(bodyFormData)
      .then(res => {
        //console.log(res)
      })
      .catch(err => console.error(err))
  }

  const onFileChange = (e) => {
    console.log(`e.target.files[0]`, e.target.files[0])
    setPicFile({ selectedFile: e.target.files[0] });
  }

  return (
    <div>
      <h1>My Puzzle Gallery</h1>
      <form encType='multipart/form-data'>
        <input type='file' name='picFile' onChange={onFileChange} />
        <br />
        <br />
        <button onClick={handleUploadClick}>Upload a picture</button>
      </form>
      <br />
      <br />
      <button onClick={handleGetClick}>Get pictures</button>
      <br />
      <br />
      <img src='https://placekitten.com/640/360' alt='kitten' />
    </div>
  );
}

client\src\services\API.js

import axios from 'axios';

const API = {
  login: (username, password) => {
    const obj = {
      username: username,
      password: password
    };
    return axios.post('/api/auth/login', obj);
  },
  register: (username, password) => {
    const obj = {
      username: username,
      password: password
    };
    return axios.post('/api/auth/register', obj);
  },
  logout: function () {
    return axios.get('api/auth/logout');
  },
  save: function (form) {
    return axios.post('api/puzzle/', form).catch(err=>console.error(err));
  },
  findAll: function () {
    return axios.get('api/puzzle/');
  },

}

export default API;

server\routes\api\puzzle\index.js

const router = require('express').Router();
const puzzleController = require('../../../controllers/puzzleController');

// Matches with '/api/puzzle'

router.route('/')
  .get(puzzleController.findAll)
  .post(puzzleController.save);

// Matches with '/api/books/:id'
router.route('/delete/:id')
  .delete(puzzleController.remove);

module.exports = router;

server\server.js

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

const passport = require('./config/passport');
const mongoose = require('mongoose');
const cors = require('cors');
const session = require('express-session');
const helmet = require('helmet');
const morgan = require('morgan');
const corsOptions = require('./config/cors.js');
const routes = require('./routes');
const { v1: uuidv1 } = require('uuid');

// console.log(uuidv1());

const PORT = process.env.PORT || 3001;
const app = express();

mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost/puzzlegallery', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  useCreateIndex: true,
  useFindAndModify: false
});
mongoose.set("useCreateIndex", true);

// Define middleware here
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

app.use(helmet({ contentSecurityPolicy: false }));
app.use(session({ secret: 'sassy', resave: false, saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());
app.use(cors(corsOptions));

app.use(morgan('dev'));
app.use(routes);

// for Reactjs ##################
// Serve up static assets (usually on heroku)
if (process.env.NODE_ENV === 'production') {
  app.use(express.static('client/build'));
}
// #################################################

if (process.env.NODE_ENV === 'production') {
  app.get('*', (_, res) => {
    res.sendFile(path.join(__dirname, '../client/build/index.html'));
  });
}



app.listen(PORT, (err) => {
  if (err) throw err;
  console.log(
    ` Server is Ready and Listening on http://localhost:${PORT}`
  ); // eslint-disable-line no-console
});

编辑: 这似乎奏效了。再次感谢!!

const path = require('path');
const router = require('express').Router();
const puzzleController = require('../../../controllers/puzzleController');
const multer = require('multer');
const { v1: uuidv1 } = require('uuid');

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, path.join(__dirname, '../../../../tmp/my-uploads'))
  },
  filename: function (req, file, cb) {
    cb(null, uuidv1())
  }
})

const upload = multer({ storage: storage });

// Matches with '/api/puzzle'

router.route('/')
  .get(puzzleController.findAll)

// Matches with '/api/books/:id'
router.route('/delete/:id')
  .delete(puzzleController.remove);

router.use(upload.single('picFile'));

router.route('/')
  .post(puzzleController.save);

module.exports = router;

你不能像这样在 save 函数中调用中间件。

我克隆了您的存储库并在 server.js 中添加了以下代码,它工作正常并且我在 req.file.

中获得了值
const multer = require('multer');
const upload = multer({ dest: 'uploads/'});

app.post('/api/puzzle/', upload.single('pictureFile'),(req,res,next)=>{
  console.log("req.file22222222", req.file);
})