DEV Community

Mihai Stanciu
Mihai Stanciu

Posted on

Uploading files to node.js server

This is a guide on how to use the multer library with express.

We start with setting up a basic form for uploading a file and other text information(optional).

I used React for this tutorial but the same result can be easily achieved with any other framework or with plain JavaScript.

Creating a basic React project

In order to start we need a working React project. Simply run this command in your terminal to set up a basic React project.

npx create-react-app <project_name>
Enter fullscreen mode Exit fullscreen mode

Note: Replace <project_name> with whatever you want to call your project.
To check that everything is working run cd <project_name> and npm start. You should see a boilerplate React app in your browser.

Creating the form for uploading

We will make a form that will be used to upload files and a title for that file.

App.js

import React from 'react';

const App = () => {
    return (
        <form>
            <input type="text" name="text" />
            <input type="file" name="file" />
            <input type="submit" value="Submit" />
        </form>
);
    };

export default App;
Enter fullscreen mode Exit fullscreen mode

Now we will set up a server using multer.js

Note: In order to start run the following command in a folder on the same level as the React project.

  1. First initialize a node project in the folder for the server.
npm init -y
Enter fullscreen mode Exit fullscreen mode

2.Then install express and multer using the following command.

npm i -D express multer cors body-parser
Enter fullscreen mode Exit fullscreen mode

3.In your package.json we need to change some things

Add the following to your scripts

"scripts": {
    "start": "node index.js"
}
Enter fullscreen mode Exit fullscreen mode

Also add type setting

"type": "module"
Enter fullscreen mode Exit fullscreen mode

4.Make a index.js file for the server

import express from 'express';
import bodyparser from 'body-parser';
import cors from 'cors';

const app = express();

app.get('/posts', (req, res) => {});

app.post('/submit', (req, res) => {});

app.listen(3030, () => console.log('server listening on port 3030'));
Enter fullscreen mode Exit fullscreen mode

We also need to set up some middleware

import express from 'express';
import bodyparser from 'body-parser';
import cors from 'cors';

const app = express();

app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use('/uploads', express.static('./uploads'));

app.get('/posts', (req, res) => {});

app.post('/submit', (req, res) => {});

app.listen(3030, () => console.log('server listening on port 3030'));
Enter fullscreen mode Exit fullscreen mode

5.Now let's prepare multer

import express from 'express';
import bodyparser from 'body-parser';
import cors from 'cors';
import multer from 'multer';

const app = express();

app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads');
  },
  filename: function (req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now() + '.jpg');
  },
});

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

app.use('/uploads', express.static('./uploads'));

app.get('/posts', (req, res) => {});

app.post('/submit', upload.single('file'), (req, res) => {});

app.listen(3030, () => console.log('server listening on port 3030'));
Enter fullscreen mode Exit fullscreen mode

6.Now make a uploads file right next to the index.js

7.Let's set up MongoDB

Run this command

npm i -D mongoose
Enter fullscreen mode Exit fullscreen mode

index.js

import express from 'express';
import bodyparser from 'body-parser';
import cors from 'cors';
import multer from 'multer';
import mongoose from 'mongoose';

const app = express();

app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads');
  },
  filename: function (req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now() + '.jpg');
  },
});

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

mongoose
  .connect('mongodb://localhost:27017/multer-test', {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(res => console.log('DB connected'))
  .catch(err => console.error(err));


app.use('/uploads', express.static('./uploads'));

app.get('/posts', (req, res) => {});

app.post('/submit', upload.single('file'), (req, res) => {});

app.listen(3030, () => console.log('server listening on port 3030'));

Enter fullscreen mode Exit fullscreen mode

Now we will create a model for the database

models/Test.js

import mongoose from 'mongoose';

const test_schema = new mongoose.Schema({
  file_path: {
    type: String,
    required: true,
  },
  description: {
    type: String,
    required: true,
  },
});

export default mongoose.model('Test', test_schema);
Enter fullscreen mode Exit fullscreen mode

And after that we can use the database

index.js

import express from 'express';
import bodyparser from 'body-parser';
import cors from 'cors';
import multer from 'multer';
import mongoose from 'mongoose';
import Test from './models/Test.js';

const app = express();

app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads');
  },
  filename: function (req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now() + '.jpg');
  },
});

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

mongoose
  .connect('mongodb://localhost:27017/multer-test', {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(res => console.log('DB connected'))
  .catch(err => console.error(err));


app.use('/uploads', express.static('./uploads'));

app.get('/posts', (req, res) => {
    Test.find({})
        .then(response => res.json(response))
        .catch(err => console.error(err));
});

app.post('/submit', upload.single('file'), (req, res) => {
    const data = new Test({ description: req.body.text, file_path: req.file.path });
    data.save()
        .then(response => console.log(response))
        .catch(err => console.error(err));
});

app.listen(3030, () => console.log('server listening on port 3030'));
Enter fullscreen mode Exit fullscreen mode

Note: This completes our server.

Now we will make a request from the server in order to upload a file

Back in our React project we run:

npm i -D axios
Enter fullscreen mode Exit fullscreen mode

src/App.js

import React, { useRef } from 'react';
import axios from 'axios';

const App = () => {
    const formRef = useRef(null);
    const submit_file = e => {
        e.preventDefault();

        const form_data = new FormData(formRef.current);

        axios({
            url: 'http://localhost:3030/submit',
            method: 'post',
            headers: { 'Content-Type': 'multipart/form-data' },
            data: form_data
        })
            .then(res => console.log(res))
            .catch(err => console.error(err));
    };

    return (
        <form onSubmit={submit_file} ref={formRef}>
            <input type="text" name="text" />
            <input type="file" name="file" />
            <input type="submit" value="Submit" />
        </form>
);
    };

export default App;
Enter fullscreen mode Exit fullscreen mode

Now we can upload files and save their path to the database

Also if we want access to our files and the data related to them we can make another axios request to http://localhost:3030/posts.

src/App.js

import React, { useRef, useState, useEffect } from 'react';
import axios from 'axios';

const App = () => {
    const formRef = useRef(null);
    const [data, setData] = useState([]);

    useEffect(() => {
        axios.get('http://localhost:3030/posts')
            .then(res => setData(res.data))
            .catch(err => console.error(err));
    }, []);

    const submit_file = e => {
        e.preventDefault();

        const form_data = new FormData(formRef.current);

        axios({
            url: 'http://localhost:3030/submit',
            method: 'post',
            headers: { 'Content-Type': 'multipart/form-data' },
            data: form_data
        })
            .then(res => console.log(res))
            .catch(err => console.error(err));
    };

    return (
        <form onSubmit={submit_file} ref={formRef}>
            <input type="text" name="text" />
            <input type="file" name="file" />
            <input type="submit" value="Submit" />
        </form>
);
    };

export default App;
Enter fullscreen mode Exit fullscreen mode

Now we have acces to the file path and text within our data array.

src/App.js

import React, { useRef, useState, useEffect } from 'react';
import axios from 'axios';

const App = () => {
    const formRef = useRef(null);
    const [data, setData] = useState([]);

    useEffect(() => {
        axios.get('http://localhost:3030/posts')
            .then(res => setData(res.data))
            .catch(err => console.error(err));
    }, []);

    const submit_file = e => {
        e.preventDefault();

        const form_data = new FormData(formRef.current);

        axios({
            url: 'http://localhost:3030/submit',
            method: 'post',
            headers: { 'Content-Type': 'multipart/form-data' },
            data: form_data
        })
            .then(res => console.log(res))
            .catch(err => console.error(err));
    };

    return (
        <>
            <form onSubmit={submit_file} ref={formRef}>
                <input type="text" name="text" />
                <input type="file" name="file" />
                <input type="submit" value="Submit" />
            </form>
            <div>
            {data.map(el => (
                <div key={el._id}>
                    <h2>{ el.description }</h2>
                    <img src={`http://localhost:3030/${el.file_path.replace('\\', '/')}`} />
                </div>
            ))}
            </div>
        </>
    );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

This is it now you can upload files through a form.

If you have any questions please address them in the comments.

I also have all the source code for a project like this onn my GitHub profile, here.

Top comments (1)

Collapse
 
pfisterruiz profile image
PfisterRuiz

If the modules mentioned above are not already installed, can I install them now using NPM. In the terminal, how to install the corresponding module . lemon spell break up