Home > front end >  Image not rendering with EJS and Multer
Image not rendering with EJS and Multer

Time:11-24

As the title states I am having issues rendering the image file that I'm uploading in my node.js application. I have included multer and the images are correctly uploading to the appropriate folder, however when referencing these images in ejs I get a

GET http://localhost:3000/public/uploads/2021-11-20T15:36:02.319Zlakeside.jpg 404 (Not Found)

When I update the href's in the index.ejs and show.ejs <div ><img src="<%= article.image %>" alt=""> </div> I get different pathing errors which lead me to believe it's just an issue with routing?

File structure

Lefiatv2
    - controllers
    - models
        - article.js
    - public
        - uploads
    - routes
        - blog.js
    - views
        - blog
            - edit.ejs
            - index.ejs
            - new.ejs
            - show.ejs
    server.js
    schemas.js

blog.js


    const express = require('express')
    const multer = require('multer')
    const Article = require('./../models/article')
    const router = express.Router()
    
    const storage = multer.diskStorage({
    
        // destination for file
        destination: function (req, file, callback) {
            callback(null, './public/uploads')
        },
        // add back the extension
        filename: function (req, file, callback) {
            callback(null, new Date().toISOString()   file.originalname)
        },
    })
    
    const fileFilter = (req, file, cb) => {
        // reject a file
        if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
          cb(null, true);
        } else {
          cb(null, false);
        }
      };
    
    // upload parameters for multer 
    
    const upload = multer({
        storage: storage,
        limits: {
            fileSize: 1024*1024*3,
        },
        fileFilter: fileFilter
    })
    
    
    
    
    router.get('/', async (req, res) => {
        const articles = await Article.find().sort({ createdAt: 'desc' })
        res.render('blog/index', { articles: articles })
    })
    
    router.get('/new', (req, res) => {
        res.render('blog/new', { article: new Article() })
    })
    
    router.get('/edit/:id', async (req, res) => {
        const article = await Article.findById(req.params.id)
        res.render('blog/edit', { article: article })
    })
    
    router.get('/:slug', async (req, res) => {
        const article = await Article.findOne({ slug: req.params.slug })
        if(article == null) res.redirect('/blog')
        res.render('blog/show', { article: article })
    })
    
    router.post('/', upload.single('image'), async (req, res, next) => {
    console.log(req.file)
    
        req.article = new Article()
        next()
    }, saveArticleAndRedirect('new'))
    
    router.put('/:id', upload.single('image'), async (req, res, next) => {
        req.article = await Article.findOneAndUpdate(req.params.id)
        next()
    }, saveArticleAndRedirect('edit'))
    
    router.delete('/:id', async (req, res) => {
        await Article.findByIdAndDelete(req.params.id)
        res.redirect('/blog')
    })
    
    function saveArticleAndRedirect(path) {
        return async (req, res) => {
            let article = req.article
            article.title = req.body.title
            article.description = req.body.description
            article.markdown = req.body.markdown
            article.image = req.file.path
        try {
           article = await article.save()
           res.redirect(`/blog/${article.slug}`)
        } catch(e) {  
            res.render(`blog/${path}`, { article: article })
        }      
        }
    }
    
    module.exports = router

article.js


    const mongoose = require('mongoose')
    const marked = require('marked')
    const slugify = require('slugify')
    const createDomPurify = require('dompurify')
    const { JSDOM } = require('jsdom')
    const dompurify = createDomPurify(new JSDOM().window)
    
    
    const articleSchema = new mongoose.Schema({
        title: {
            required: true,
            type: String
        },
        description: {
            type: String
        },
        markdown: {
            type: String,
            required: true
        },
        createdAt: {
            type: Date,
            default: Date.now
        },
        slug: {
            type: String,
            required: true,
            unique: true
        },
        sanitizedHtml: {
            type: String,
            required: true
        },
        image: {
            type: String,
            data: Buffer,
        }
            
    
    
       
    }); 
    
    
    articleSchema.pre('validate', function(next) {
        if (this.title) {
            this.slug = slugify(this.title, { lower: true, strict: true })
        }
    
        if (this.markdown) {
            this.sanitizedHtml = dompurify.sanitize(marked(this.markdown))
          }
    
        next()
    
    })
    
    module.exports = mongoose.model('Article', articleSchema)

show.ejs


    <div class="container">
        <div class=""><img src="<%= article.image %>" alt=""> </div>
        <h1 class="mb-2"><%= article.title %> </h1>
    
        <div class="text-muted mb-2">
            <%- article.createdAt.toLocaleDateString() %>
        </div>
        <div class="text-muted mb-2"><%= article.slug %></div>
        <a href="/blog" class="btn btn-secondary">All Articles</a>
        <a href="/blog/edit/<%= article.id %> " class="btn btn-info">Edit</a>
    
        <div>
            <%- article.sanitizedHtml %>
        </div>
    
    </div>

index.ejs


    <link rel="stylesheet" href="/stylesheets/blog.css">
    
    <div >
    
        <!-- <div >
            <div >
                <p>Do your dreams follow the clouds?</p>
                <a href="/trips" >Follow Our Adventures</a>
            </div>
        </div> -->
        <div >
            <div >
                <div >
                    <h3 >Do your dreams follow the clouds?</h3>
                    <form action="#" >
                        <div > <input type="email"
                                 id="email"
                                placeholder="Your Email" name="email"> </div>
                        <div > <button type="submit" >Follow Our
                                Adventures</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
        <h1 >Latest Articles</h1>
        <a href="/blog/new" >New Article</a>
    
        <% articles.forEach(article =>  { %>
        <div >
            <div >
                <div >
                    <div >
                        <h4 > <%= article.title %> </h4>
                        <div >
                            <%- article.createdAt.toLocaleDateString() %>
                        </div>
                        <div >
                            <%= article.description %>
                        </div>
                    </div>
                    <div >
                        <img src="<%= article.image %>" alt="">
                    </div>
                </div>
                <div >
                    <a href="/blog/<%= article.slug %>">Read More</a>
                    <a href="/blog/edit/<%= article.id %>" >Edit</a>
                    <form action="/blog/<%= article.id %>?_method=DELETE " method="POST" >
                        <button type="submit" >Delete</button>
                    </form>
                </div>
            </div>
        </div>
        <% }) %>
    </div>

CodePudding user response:

add this to your server.js file
app.use(express.static(path.join(__dirname, 'public')))

app.use('/uploads', express.static(path.join(__dirname, 'uploads')))

  • Related