我无法将文件上传到我使用 node js multer 指定的目录

Posted

技术标签:

【中文标题】我无法将文件上传到我使用 node js multer 指定的目录【英文标题】:I cannot upload files to the directory I specified using node js multer 【发布时间】:2020-07-17 08:19:27 【问题描述】:

我使用节点 js 创建了一个 Web 服务。我创建了一个带有 React 界面的表单,并添加了用户信息和文件上传。我将此信息保存到 mongodb。我想使用 multer 将文件保存到节点 js 服务器,但没有将文件添加到我指定的目录中。我需要解决什么问题?

路线

const express = require('express')
const User = require('../models/index')
const router = express.Router()
const multer = require('multer')

const storage = multer.diskStorage(
    destination: function(req, file, cb) 
        cb(null, './public/uploads');
    ,
    filename: function (req, file, cb) 
        cb(null , file.originalname);
    
);

const upload = multer( storage: storage )

/* create new*/
router.post('/', upload.single('image'), (req,res)=>

    user = new User(
        name:req.body.name,
        email:req.body.email,
        password:req.body.password,
        img: req.file
    );

    user.save(()=>
        res.json(user)
    )
);

/* find all users */
router.get('/', (req, res) => 
    User.find(,(err,data) =>
        res.json(data)
    )
);

/* find user by id */
router.get('/:id',(req, res) =>
    User.findById(req.params.id, (err, data) =>
        res.json(data)
    )
);

/* delete user by id */
router.delete('/:id',async (req, res) =>
    await User.findByIdAndDelete(req.params.id)
    res.json('message':'deleted')
);

/* update */
router.put('/:id', async (req, res)=>
    await User.findByIdAndUpdate(req.params.is, req.body)
    res.json('message':'updated')
);

module.exports = router;

服务器/index.js

const express = require('express');
const mongoose = require('mongoose');
const mongodb = require('mongodb');
const cors = require('cors');
mongoose.connect('mongodb://localhost:27017/admin?authSource=$[authSource] --username $[username]', useNewUrlParser : true);
const app = express();

app.use(express.json());
app.use(cors());
app.use(express.urlencoded(extended:true));

app.use('/api',require('./routes/index'));

const port = process.env.PORT || 8080;

app.listen(port);

module.exports =  new mongoose.model('User', newSchema);

反应方面

import React, Component from 'react';
import axios from 'axios';

class App extends React.Component 

    constructor(props) 
        super(props);
        this.state = 
            users: [],
            id: 0,
            name: '',
            email: '',
            password: '',
            img: ''
        
    

    componentDidMount() 
        try 
            axios.get('http://localhost:8080/api')
                .then((res) => 
                    this.setState(
                        users: res.data,
                        id: 0,
                        name: '',
                        email: '',
                        password: '',
                        img: ''
                    )
                )
         catch (e) 
            console.log(e)
        
    

    nameChange = event => 
        this.setState(
            name: event.target.value
        )
    

    emailChange = event => 
        this.setState(
            email: event.target.value
        )
    

    passwordChange = event => 
        this.setState(
            password: event.target.value
        )
    

    fileSelectedHandler = event =>
        this.setState(
            img : event.target.files[0]
        )
    

    submit(event, id) 
        event.preventDefault();

        const data = new FormData();

        data.append('name', this.state.name);
        data.append('password', this.state.password);
        data.append('email', this.state.email);
        data.append('image', this.state.img);

        if (id === 0) 
            axios.post('http://localhost:8080/api', data).then(()=>
                this.componentDidMount()
            )

         else 
            axios.put('http://localhost:8080/api/'+id, data).then(()=>
                this.componentDidMount()
            )
        
    

    deleteUser(id) 
        try 
            axios.delete('http://localhost:8080/api/' + id)
                .then((res) => 
                    this.componentDidMount()
                )
            console.log('Deleted successfully.')
         catch (e) 
            console.log(e)
        
    

    editUser(id) 
        try 
            axios.get('http://localhost:8080/api/' + id)
                .then((res) => 
                    console.log(res.data)
                    this.setState(
                        id:res.data._id,
                        name: res.data.name,
                        email: res.data.email,
                        password: res.data.password,
                        img : res.data.img.name
                    )
                )
         catch (e) 
            console.log(e)
        
    

    render() 
        return (
            <div className="row">
                <div className="col s6">
                    <form onSubmit=(e) => this.submit(e, this.state.id)>
                        <div className="input-field col s12">
                            <i className="material-icons prefix">person</i>
                            <input value=this.state.name onChange=(e) => this.nameChange(e) type="text" id="autocomplete-input"
                                   className="autocomplete" required/>
                            <label htmlFor="autocomplete-input">Name</label>
                        </div>
                        <div className="input-field col s12">
                            <i className="material-icons prefix">mail</i>
                            <input value=this.state.email onChange=(e) => this.emailChange(e) type="email" id="autocomplete-input"
                                   className="autocomplete" required/>
                            <label htmlFor="autocomplete-input">Email</label>
                        </div>
                        <div className="input-field col s12">
                            <i className="material-icons prefix">***_key</i>
                            <input value=this.state.password onChange=(e) => this.passwordChange(e) type="password" id="autocomplete-input"
                                   className="autocomplete" required/>
                            <label htmlFor="autocomplete-input">Password</label>
                        </div>
                        <div className="input-field col s12">
                            <input type="file" name="file" onChange=(e) => this.fileSelectedHandler(e)/>
                        </div>
                        <br/>
                        <button className="btn waves-effect waves-light right blue" type="submit" name="action">Submit
                            <i className="material-icons right">send</i>
                        </button>
                    </form>
                </div>
                <div className="col s6">
                    <table>
                        <thead>
                        <tr>
                            <th>Name</th>
                            <th>Email</th>
                            <th>Password</th>
                            <th>IMG</th>
                            <th>Edit</th>
                            <th>Delete</th>
                        </tr>
                        </thead>
                        <tbody>
                        this.state.users.map(user =>
                            <tr key=user._id>
                                <td>user.name</td>
                                <td>user.email</td>
                                <td>user.password</td>
                                <td>
                                    <img src="./public/uploads/user.img.name" />
                                </td>
                                <td>
                                    <button onClick=(e) => this.editUser(user._id)
                                            className="btn waves-effect waves-light green" type="submit" name="action">
                                        <i className="material-icons right">edit</i>
                                    </button>
                                </td>
                                <td>
                                    <button onClick=(e) => this.deleteUser(user._id)
                                            className="btn waves-effect waves-light red" type="submit" name="action">
                                        <i className="material-icons right">delete</i>
                                    </button>
                                </td>
                            </tr>
                        )
                        </tbody>
                    </table>
                </div>
            </div>
        );
    


export default App;

【问题讨论】:

【参考方案1】:

我可以在您的代码中看到两个问题。

在服务器端,上传的文件位于请求对象的file-property 下,而不是body-property。您还需要将名称设置为multer single-call 上上传的文件,即image:

router.post('/', upload.single('image'), (req,res)=>
...
    const image = req.file; // req.file contains the image
    // req.body holds the other fields like name, email, ...
...
);

在反应方面,您应该发送 formData 而不是 json(json 是默认值):

const data = new FormData();
data.append('image', this.state.img);
data.append('email', this.state.name);
// ... append the remaining fields
axios.post('http://localhost:8080/api', data)
.then(() => 
    this.componentDidMount()
);

// in the view also use the correct name
...
<input type="file" name="image" onChange=(e) => this.fileSelectedHandler(e)/>
...

【讨论】:

我试图实现你所说的,我编辑了我在问题中分享的代码块。如果我问,你能检查一下吗?这次没有post请求,以前可以在mongodb上注册name、password、email等字段,但现在不行。表单数据不正确吗? 不幸的是我现在不能自己测试它,但我认为你需要添加一个body-parser而不是express.json()。请检查这些答案-> ***.com/a/43197040/3761628 ***.com/a/61025053/3761628

以上是关于我无法将文件上传到我使用 node js multer 指定的目录的主要内容,如果未能解决你的问题,请参考以下文章

我无法使用 node js 将来自 Json 的数据注入带有 angularjs 的 html

我将如何限制 node.js 中服务器的上传速度?

如何使用 node.js 获取图像上传进度并在我的 iphone 应用程序中使用它

无法使用 express 和 multer 运行 node.js 服务器以在节点中上传文件

如何修复 Node.js 中的“413 请求实体太大”错误

上传图片文件到服务器node.js express axios