File Upload using Multer
Jakaria Masum

Jakaria Masum @jakaria

About: Full-Stack Developer | MERN Stack | Next.js | TypeScript

Location:
Bogura, Bangladesh
Joined:
Jun 26, 2024

File Upload using Multer

Publish Date: Apr 24
0 0

In this post, you'll learn how to build a clean, reusable backend API in Node.js + TypeScript using Express and Multer to handle file uploads. We'll keep it simple — no file type restrictions or size limits — just basic upload functionality that saves files using their original name.


🛠 Tech Stack

  • Express: Web framework for Node.js
  • Multer: Middleware for handling multipart/form-data (file uploads)
  • TypeScript: Optional static typing
  • MVC Structure: For clean separation of logic

🗂 Folder Structure

file-upload-api/
├── controllers/
│   └── upload.controller.ts
├── middleware/
│   └── upload.middleware.ts
├── routes/
│   └── upload.route.ts
├── services/
│   └── upload.service.ts
├── uploads/  (created automatically)
├── index.ts
├── tsconfig.json
└── package.json
Enter fullscreen mode Exit fullscreen mode

📦 Step 1: Install Dependencies

npm install express multer
npm install -D typescript ts-node-dev @types/node @types/express @types/multer
Enter fullscreen mode Exit fullscreen mode

Add a simple tsconfig.json if you don’t have one yet:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true
  },
  "include": ["./**/*.ts"]
}
Enter fullscreen mode Exit fullscreen mode

✍️ Step 2: Multer Middleware

middleware/upload.middleware.ts

import multer from 'multer';
import path from 'path';
import fs from 'fs';

// Ensure uploads directory exists
const uploadDir = path.join(process.cwd(), 'uploads');
if (!fs.existsSync(uploadDir)) {
  fs.mkdirSync(uploadDir, { recursive: true });
}

const storage = multer.diskStorage({
  destination: (_req, _file, cb) => cb(null, uploadDir),
  filename: (_req, file, cb) => {
    const timestamp = Date.now();
    cb(null, `${timestamp}-${file.originalname}`);
  },
});

export const upload = multer({ storage });
Enter fullscreen mode Exit fullscreen mode

💼 Step 3: Upload Service

services/upload.service.ts

export const handleUploadService = (file: Express.Multer.File) => {
  return {
    message: 'File uploaded successfully!',
    originalName: file.originalname,
    filename: file.filename,
    path: file.path,
    size: file.size,
  };
};
Enter fullscreen mode Exit fullscreen mode

📤 Step 4: Upload Controller

controllers/upload.controller.ts

import { Request, Response } from 'express';
import { handleUploadService } from '../services/upload.service';

export const uploadFile = (req: Request, res: Response) => {
  if (!req.file) {
    return res.status(400).json({ error: 'No file uploaded' });
  }

  const data = handleUploadService(req.file);
  res.status(200).json(data);
};
Enter fullscreen mode Exit fullscreen mode

🛣 Step 5: Define the Route

routes/upload.route.ts

import { Router } from 'express';
import { upload } from '../middleware/upload.middleware';
import { uploadFile } from '../controllers/upload.controller';

const router = Router();

router.post('/file', upload.single('file'), uploadFile);

export default router;
Enter fullscreen mode Exit fullscreen mode

🚀 Step 6: Initialize Express Server

index.ts

import express from 'express';
import uploadRoute from './routes/upload.route';

const app = express();
const PORT = 3000;

app.use(express.json());
app.use('/api/upload', uploadRoute);

app.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

🧪 Test It with Postman

  • Method: POST
  • URL: http://localhost:3000/api/upload/file
  • Body: form-data
    • Key: file (type: File)
    • Select a file from your system

You should get a JSON response like:

{
  "message": "File uploaded successfully!",
  "originalName": "video.mp4",
  "filename": "1713967431914-video.mp4",
  "path": "/uploads/1713967431914-video.mp4",
  "size": 123456
}
Enter fullscreen mode Exit fullscreen mode

✅ Conclusion
You now have a robust, scalable backend setup for handling video uploads using Express, TypeScript and Multer. It saves with original file names (timestamp-prefixed), and follows clean code separation via MVC.


Comments 0 total

    Add comment