Search code examples
node.jsangularexpresscrud

Can't post image file to Express server with Angular 18.0.6


I am not a native English speaker so my english might be hard to read.

I am currently developing Angular(18.0.6) application and trying to implement CRUD using express and mysql. What I am trying is to implement file upload function using Multer. I searched some docs and wrote codes but I am really confused what the heck is going on.

Here is service components. A file data is in "sticker". I made sure that file data can be shown in console.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class PutstickerService {
  private uploadUrl = 'http://localhost:3000/putNewSticker';

  constructor(private http: HttpClient) { }

  uploadImage(sticker: File): Observable<any> {
    console.log(sticker);
    const data = new FormData();
    data.append('sticker', sticker, sticker.name);
    return this.http.post<any>(this.uploadUrl, data);
  }
}

And then, this is mjs file which recieve FormData and post data to mySQL.

import express from 'express';
import connection from '../config/database.mjs';
import multer from 'multer';
import path from 'path';

const router = express.Router();

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, 'public/uploads/');
    },
    filename: function (req, file, cb) {
        cb(null, Date.now() + path.extname(file.originalname)); // Adds a timestamp to avoid filename conflicts
    }
});

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

router.get('/test', (req, res) => {
    console.log("test");
});

router.post('/putNewSticker', upload.single('sticker'), (req, res) => {
    if (!req.file) {
        return res.status(400).send('No file uploaded.');
    }

    console.log(`File uploaded: ${req.file.filename}`);
    const filePath = req.file.path.replace('public/', '');
    const sql = 'INSERT INTO stickers (sticker) VALUES (?)';

    connection.query(sql, [filePath], (err, result) => {
        if (err) {
            console.error('Error inserting image path to MySQL:', err);
            return res.status(500).send('Internal Server Error');
        }

        res.send({ message: 'Image uploaded successfully', path: filePath });
    });
});

export default router;

I put console.log but nothing shown in terminal. So I think this path didn't even read. I made sure that "/test" could work. so I don't think this whole file is wrong. just around multer or post code.

This is my first time to ask question so if you need more information, please tell me.

I am expecting to understand why "/putNewSticker" path can't be read when "/test" path is read. I can't keep developing if I can't have error or something. It just doesn't work.

I really need help. Thank you so much.

EDITED

This is how im mounting router.

import express from 'express';
import path from 'path';
import cors from 'cors';
import bodyParser from 'body-parser';
import { fileURLToPath } from 'url';
import { dirname } from 'path';

import indexRouter from './routes/index.mjs';
import usersRouter from './routes/users.mjs';
import stickersRouter from './routes/stickers.mjs';
import putStickerRouter from './routes/putSticker.mjs';

const app = express();

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

app.use(bodyParser.json());
app.use(cors());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/', usersRouter);
app.use('/', stickersRouter);
app.use('/', putStickerRouter);

const port = 3000;
app.listen(port, () => {
    console.log(`Server running on port ${port}`);
});


Solution

  • The problem is on the server: you're mounting multiple route handlers on the same route: /, and as order matters (those loaded first, run first), most likely the first middleware - indexRouter - swallows all requests, never reaching stickers handler, most likely it finishesh the response, or it's pending if not.

    So, try changing route paths for each route, for example:

    app.use('/', indexRouter);
    app.use('/users', usersRouter);
    app.use('/stickers', stickersRouter);
    app.use('/put-stickers', putStickerRouter);
    

    and request URLs accordingly:

    private uploadUrl = 'http://localhost:3000/put-stickers/putNewSticker';
    

    see:

    The order of middleware loading is important: middleware functions that are loaded first are also executed first.

    If myLogger is loaded after the route to the root path, the request never reaches it and the app doesn’t print “LOGGED”, because the route handler of the root path terminates the request-response cycle.

    Writing middleware for use in Express apps