# How to upload file using ExpressJS(NodeJS) - Multer

It took me 4-days and 100+ attempts to solve this simple issue of uploading a file using node. 

And the moment I got it right, I was like...phewww

![phew gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/szl49by3a0nfymfp6wct.gif)
 

Here is how I solved this issue.

By creating a - 
- Simple node server.
- Middleware to process files.
- POST route to accept files.
- Route to serve files.
- Middleware to Handle CORS issue(you won't get this issue in postman).
 

**Node server using express**

- Initialize the project using below command

> node init

- Install the required dependencies.

> using npm -> `npm i express dotenv`

> using yarn -> `yarn add express dotenv` 

- Create server.js and paste below code 

```js

const express = require("express");
const dotenv = require("dotenv");

const app = express();

dotenv.config(); // <-- To use.env file

app.use(express.json());
/*
express.json() middleware helps us to parse all HTTP requests

like --> req.body

And express.json() middleware always should be at the top

*/

const PORT = process.env.PORT || 5000;
app.listen(
  PORT,
  console.log(`Server is up and running on port ${PORT}`)
);

```
Now run the node server using below command

> node server.js


**Create a middleware to process files.**

Install the dependencies

> using npm -> `npm i multer`
 
> using yarn -> `yarn add multer` 

Create `processFile.js` file and paste below code in it and create `upload` folder to store uploaded files in it.
 
```js
const multer = require("multer");
const path = require("path");

const MIME_TYPES = {
  "image/jpg": "jpg",
  "image/jpeg": "jpg",
  "image/png": "png",
  // you can add more here
};

const storage = multer.diskStorage({
  destination: (req, file, callback) => {
    callback(null,path.join(__dirname, './upload'));
   // Note ./upload path should be relative. Change this path according to your folder structure
  },
  filename: (req, file, callback) => {
    const name = file.originalname.split(" ").join("_");
    const extension = MIME_TYPES[file.mimetype];
    callback(null, name + Date.now() + "." + extension);
  },
});

const processFile = multer({ storage: storage }).single("file"); //<--here `file` key
/*
Look at the last example of how we will use `file` key to 
upload files using form data and postman.

For accepting multiple files change above line to 

const processFile = multer({ storage: storage }).array('file', 12);
Where 12 is the number of files you want to accept.

*/

module.exports = processFile;

```
 
**Create a POST route to accept file.**

Paste below code in server.js file 

_For uploading single file_
```js
const processFile = require("./processFile");

app.post("/api/upload", processFile, (req, res, next) => {

  const url = req.protocol + "://" + req.get("host");

  const file = url + "/files/" + req.file.filename;
   
  res.status(201).json({
    message: "Success",
    file: file,
  });
});
```

_For uploading multiple files_

```js
const processFile = require("./processFile");

app.post("/api/upload", processFile, (req, res, next) => {
  const files = []
  const url = req.protocol + "://" + req.get("host");
  req.files.forEach(file=>{
    const file_url = url + "/files/" + file.filename;
    files.push({
      url: file_url,
    });
  })

  res.status(201).json({
    message: "files saved successfully!",
    files,
  });
});
```

So far you would be able to store files in your `upload` folder but you can't access files using links you are receiving in the response and for that, we need to serve those files.


**Serve uploaded files**

Add below code in `server.js` file and restart the server.
```js
const path = require("path");

app.use("/files", express.static(path.join(__dirname, "upload")));
```

Now you should be able to see the files if you visit the links. 


**CORS (Cross-Origin Resource Sharing)**

Note: You won't face this issue in the postman but in your client-side app you will face this issue.

![cors error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l39k1ppbiv49xuey10di.png)
 
To resolve the CORS issue

- Create a cors middleware.
- Apply cors middleware at the top of your file

```js

const cors = (req, res, next) => {
  const origin = "*"; // <-- change this in production
  res.setHeader("Access-Control-Allow-Origin", origin);
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content, Accept, Content-Type, Authorization"
  );
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, POST, PUT, DELETE, PATCH, OPTIONS"
  );
  next();
};

app.use(cors); // <-- Should be at the top

```   


**Upload file from client**

```js

  const data = new FormData();
  data.append("file", FILE_URI);

  fetch("http://localhost:5000/api/upload", {
    method: "post",
    body: data,
  })
  .then((res) => res.json())
  .catch((err) => {
     console.log(err);
  });
```


![upload file using postman](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vm52lp4d26otr16k06dy.png)

And That's how I solved this issue. Let me know if you have any doubt.

---
_**follow me for more such blog posts.**_

[Twitter](https://twitter.com/AamChora) || [Linkedin](https://www.linkedin.com/in/hemendrakhatik/)
