--- type: article wp_id: 657 title: 'Uploading Images - EJS, Multer, and Express' date: '2021-03-01T04:05:42' slug: 'uploading-images-ejs-multer' image: name: 'uploading-images-ejs-multer.png' width: 2560 height: 1280 status: 'published' description: "In this article I'm going to show you how to upload an image from an ejs frontend to an express server using a library called multer. This will allow us to store the image in the server's file system so they can be uploaded and downloaded by any client." tags: ['javascript', 'node', 'ejs'] --- In this article I'm going to show you how to upload an image from an ejs frontend to an express server using a library called multer. This will allow us to store the image in the server's file system so they can be uploaded and downloaded by any client. ## Starter App Let's start with a basic Express app: **app.js** ```js const express = require('express') const app = express() app.set('view engine', 'ejs') app.get('/', (req, res) => { res.render('index') }) app.post('/saveImage', (req, res) => { console.log(req.body) res.send('ok') }) app.listen(8080, () => console.log("listening on port 8080")) ``` This has a two routes: - a get route that renders an ejs template called `index.ejs` and - a post route that just logs the request body and sends back a response. **index.ejs** ```html
<%= description %>
``` This page just displays the description and the image that was uploaded. If you try to upload an image now, you should see everything is working correctly, **except** the image is not showing up. That's because we're trying to access the image from the express server, but express doesn't know how to serve the images yet. ## Download Image The image is currently being stored in a directory called `images` on the server. That's great, but there's currently no way of getting the image back from the server. We want to allow the client to request the image in an img tag like this: ```html ``` Then the server needs to send the image to the client. This can be done in many ways, but the easiest way is to just let express serve these as static files: ```js app.use('/images', express.static('images')) ``` This allows anyone to view any image in the images directory. This might be exactly what you want, then yay, you're done. But you might want to keep images private and only allow authorized users to view images. In that case, you'll want to do something more like this: ```js const fs = require('fs') app.get('/images/:imageName', (req, res) => { // do a bunch of if statements to make sure the user is // authorized to view this image, then const imageName = req.params.imageName const readStream = fs.createReadStream(`images/${imageName}`) readStream.pipe(res) }) ``` ## Final Code Here's what the final code might look like for this app. The react app posts and image and then shows that image in an `img` tag. The server stores the image in its file system and serves the images when a request for an image is made: **app.js** ```js const express = require('express') const multer = require('multer') const fs = require('fs') const app = express() const upload = multer({ dest: 'images/' }) app.set('view engine', 'ejs') app.get('/', (req, res) => { res.render('index') }) app.post('/saveImage', (req, res) => { const imagePath = req.file.path const description = req.body.description // Save this data to a database probably console.log(description, imagePath) res.render('savedImage', {description, imagePath}) }) app.get('/images/:imageName', (req, res) => { // do a bunch of if statements to make sure the user is // authorized to view this image, then const imageName = req.params.imageName const readStream = fs.createReadStream(`images/${imageName}`) readStream.pipe(res) }) app.listen(8080, () => console.log("listening on port 8080")) ``` **index.ejs** ```html<%= description %>
```