multer使用节点js和mongodb服务器的文件上传问题

时间:2020-04-02 14:25:13

标签: javascript node.js reactjs mongodb

我使用node js,react js,mongodb创建了一个应用程序。我想使用multer上传文件,但是文件不上传。我与您共享了为前端和后端编写的代码块。如何使用multer将imgae成功注册到mongodb。我在互联网上进行了很多搜索,但我非常困惑。如果可以的话,我会很高兴。

模型

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

newSchema = new Schema({
    name : String,
    email : String,
    password : String,
    img:{
        type: String
    }
})

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

后端-路由/ index.js

const express = require('express')
const User = require('../models/index')
const router = express.Router()
//
const multer = require('multer')
const uuidv4 = require('uuid/v4')
const DIR = './public/';

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, DIR);
    },
    filename: (req, file, cb) => {
        const fileName = file.originalname.toLowerCase().split(' ').join('-');
        cb(null, uuidv4() + '-' + fileName)
    }
});

var upload = multer({
    storage: storage,
    fileFilter: (req, file, cb) => {
        if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
            cb(null, true);
        } else {
            cb(null, false);
            return cb(new Error('Only .png, .jpg and .jpeg format allowed!'));
        }
    }
});

//

/* 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'})
})

/* create */
router.post('/',(req,res)=>{
    const url = req.protocol + '://' + req.get('host')
    const user = new User({
        name:req.body.name,
        email:req.body.email,
        password:req.body.password,
        img: url + '/public/' + req.file.filename
    })

    user.save(()=>{
        res.json(user)
    })
})

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

module.exports = router

前端-反应端/App.js

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

    submit(event, id) {
        event.preventDefault()
        if (id === 0) {
            axios.post('http://localhost:8080/api', {
                name: this.state.name,
                email: this.state.email,
                password: this.state.password,
                img: this.state.img
            }).then(()=>{
                this.componentDidMount()
            })

        } else {
            //axios.put('http://localhost:8080/api/'+id, {
            axios.put('http://localhost:8080/api/${id}', {
                name: this.state.name,
                email: this.state.email,
                password: this.state.password,
                img: this.state.img
            }).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: this.state.img
                    })
                })
        } 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">vpn_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>
                        <br/>
                        <button className="btn waves-effect waves-light right blue" type="submit" name="action">Submit
                            <i className="material-icons right">send</i>
                        </button>
                        <div>
                            <input type="file" id="myFile" name="filename"/>
                        </div>
                    </form>
                </div>
                <div className="col s6">
                    <table>
                        <thead>
                        <tr>
                            <th>Name Surname</th>
                            <th>Email</th>
                            <th>Password</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>
                                    <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;

2 个答案:

答案 0 :(得分:0)

将文件(已转换为字符串)上传到MongoDB并不是一个好习惯。我建议为此使用文件系统或服务,例如AWS S3。

之所以这样的做法不好,是因为诸如S3之类的服务可伸缩性更高,因为图像存储在多个服务器上,而诸如S3之类的服务则可以在content delivery network之后运行,该How to properly handle files upload using Node.js Express backend?会将图像的副本存储在世界各地的服务器。

要在文件系统上存储文件,请参见How do I save a file to MongoDB?

如果文件很小,并且您希望将其内容存储在MongoDB上,请参见{{3}}。

答案 1 :(得分:0)

您应该在axios "Content-Type: "multipart/form-data"请求中传递标头-post。之后,您应该可以在Express路线的req.files中找到文件。

之后,您应该可以将文件上传到MongoDB。

尽管如此,您应该考虑使用AWS S3或Filestack之类的服务来存储文件,同时仅将URL存储在MongoDB中。

希望这会有所帮助!