【问题标题】:File upload issue with multer using node js and mongodb server使用节点 js 和 mongodb 服务器的 multer 文件上传问题
【发布时间】:2020-04-02 14:25:13
【问题描述】:

我使用 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

前端 -react 端 /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;

【问题讨论】:

    标签: javascript node.js reactjs mongodb


    【解决方案1】:

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

    之后,您应该能够将文件上传到 MongoDB。

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

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

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

      这不是好的做法的原因是,像 S3 这样的服务更具可扩展性,因为图像存储在多个服务器上,而像 S3 这样的服务可以在 content delivery network 后面运行,content delivery network 将图像的副本存储在所有服务器上全世界。

      要在文件系统上存储文件,请参阅How to properly handle files upload using Node.js Express backend?

      如果文件很小并且您希望将其内容存储在 MongoDB 上,请参阅How do I save a file to MongoDB?

      【讨论】:

      • 我该如何实现?
      • 哪一部分,S3 或将小文件保存为 MongoDB 中的字符串?
      • 其实我的目标是给mongodb写一张小用户照片,每个用户一张。一些简单的事情。
      • 图片有多小?它们是在前端还是后端调整大小?
      • 尺寸没有设置,但我不会添加非常大尺寸的照片。我做这个项目是出于试用目的,但我无法正式注册到 mongodb。
      猜你喜欢
      • 2020-07-16
      • 2017-10-20
      • 2017-08-30
      • 2016-06-25
      • 1970-01-01
      • 2018-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多