[Fixed] GET Request for Image to Angular Component returns 404 Not Found

Issue

I am trying to upload and retrieve images from my mongodb database. I am using multer for the image uploads and express and mongoose for the GET/POST requests. So far I am successfully able to upload the image to the database and retrieve it using my Angular Service. The data for the image i.e. the _id, name and avatar values are all successfully fetched by my service. But when I try to display the image in my component, it gives me this error in the browser console:

GET http://localhost:3000/public/image-1617990660620.png 404 (Not Found)

I am unable to figure out why this path is incorrect. My images are being served in the public folder. Everything else is working fine except this 404 error.

My server.js file looks like this:

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const multer = require('multer');
const cors = require('cors');
const passport = require('passport');
const mongoose = require('mongoose');
const dotenv = require('dotenv');
const session = require('express-session');
const multipart = require('connect-multiparty');
const multipartMiddleware = multipart();


//import the database configuration file and connect the server to the db using mongoose
const config = require('./config/db');

mongoose.connect(config.database,{
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useFindAndModify: false,
    useCreateIndex: true
});

//initialize app

const app = express();

app.use(cors());


//static files access
app.use(express.static(path.join(__dirname, 'public')));

//initialize bodyparser, passport and exress-session middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

app.use(session({
  secret: 'keyboard cat',
  resave: true,
  saveUninitialized: true,
  //cookie: { secure: true }
}));

app.use(passport.initialize());
app.use(passport.session());  


require('./config/passport')(passport);


//routes

app.use('/users', require('./routes/users')); //main route users which will lead to register and login etc.
app.use('/blogs', require('./routes/users'));
app.use('/gallery', require('./routes/users'));

//port number we use
const port = 3000;

//start server
app.listen(port,
    console.log(`Server Running in ${process.env.NODE_ENV} mode on port ${port} and database on ${config.database}`)
);

My multer confifuration and my GET and POST requests:

const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
const jwt = require('jsonwebtoken');
const multer = require('multer');
const User = require('../models/User');
const Post = require('../models/Post');
const Favorites = require('../models/Favorites');
const Gallery = require('../models/Gallery');
const config = require('../config/db');
const path = require('path');

// Multer Storage


const storage = multer.diskStorage({
    destination: (req, file, cb) => {
      cb(null, 'public');
    },
    filename: (req, file, cb) => {
      console.log(file);
      var filetype = '';
      if(file.mimetype === 'image/gif') {
        filetype = 'gif';
      }
      if(file.mimetype === 'image/png') {
        filetype = 'png';
      }
      if(file.mimetype === 'image/jpeg') {
        filetype = 'jpg';
      }
      cb(null, 'image-' + Date.now() + '.' + filetype);
    }
});

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


router.post('/archive', upload.single('image'), async function(req, res, next) {
  const name = req.file.filename;
  const avatar = 'http://localhost:3000/public/' + req.file.filename;
  const gallery = new Gallery({
    name,
    avatar
  });
  const createdGallery = await gallery.save();
  res.status(200).json({
    gallery: {
      ...createdGallery._doc
    }
  });
  console.log(createdGallery);
  });

router.get("/archive", async (req, res, next) => {
  const images = await Gallery.find();
  res.status(200).json({ images });
});

The HTML for my Component:

<app-header></app-header>
<h1>All Images</h1>
<hr />
<div *ngIf="images?.length > 0">
  <div *ngFor="let image of images" class="image">
    <img [src]="image.avatar" [alt]="image.name" />
    <div>
      <span>{{ image.name }}</span>
    </div>
  </div>
</div>

And the Component Type Script file:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { NgxSpinnerService } from "ngx-spinner";
import { ImageService } from '../Services/image.service';
import { Gallery } from "../post/gallery";
import { Subscription } from "rxjs";

 @Component({
   selector: 'app-archive',
   templateUrl: './archive.component.html',
   styleUrls: ['./archive.component.scss']
 })
 export class ArchiveComponent implements OnInit, OnDestroy {

   public images: Gallery[] = [];
   private imageSubscription: Subscription;

   constructor(
     private spinner: NgxSpinnerService,
     private imageService: ImageService) { }


   ngOnInit(): void {

     this.imageService.getImages();
     this.imageSubscription = this.imageService
      .getImagesStream()
      .subscribe((images: Gallery[]) => {
        this.images = images;
        //console.log(images);
      });

     this.spinner.show();
     setTimeout(() => {
      /** spinner ends after 5 seconds */
      this.spinner.hide();
    }, 3000);

   }

    ngOnDestroy() {
    this.imageSubscription.unsubscribe();
  }

 }

Can someone please guide me on what causes this error and how I can solve it? I am rather new to the MEAN Stack and any guidance and help is greatly appreciated. Thank You Very Much.

Solution

The Mistake: The Angular Component cannot find any folder named ‘public’ to access images because I have not specified any path to that folder to be accessed in my server.js.

The Solution: Add the following line of code:

app.use('/public', express.static(path.join('public')));

This line ensures that with the url http://localhost:3000/ I can access the public folder. Otherwise it was simply set up for serving static files.

Leave a Reply

(*) Required, Your email will not be published