0% found this document useful (0 votes)
7 views17 pages

Part 4 - NodeJS-File-Upload-Tutorial

This document provides a step-by-step guide for implementing image upload functionality in a Node.js API using Multer for file handling and Sharp for image processing. It covers installation, configuration, file validation, error handling, and saving uploaded images to a user profile, along with serving the files statically. The guide also includes testing instructions and troubleshooting tips to ensure a smooth implementation.

Uploaded by

mkozhakhmetovv
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views17 pages

Part 4 - NodeJS-File-Upload-Tutorial

This document provides a step-by-step guide for implementing image upload functionality in a Node.js API using Multer for file handling and Sharp for image processing. It covers installation, configuration, file validation, error handling, and saving uploaded images to a user profile, along with serving the files statically. The guide also includes testing instructions and troubleshooting tips to ensure a smooth implementation.

Uploaded by

mkozhakhmetovv
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Part 4

Image & File Uploads


Multer, Validation & Image Processing

Quick Step-by-Step Guide

Backend Development Lab


Table of Contents
Table of Contents ...............................................................................................................................2

What You Will Learn ...........................................................................................................................3

STEP 1: Install Multer & Sharp ............................................................................................................4


Create Upload Directory ......................................................................................................................4

STEP 2: Basic File Upload Setup ..........................................................................................................5


Create lib/[Link]..............................................................................................................................5

Add Upload Endpoint ...........................................................................................................................5

Update [Link] .......................................................................................................................................6

STEP 3: File Validation ........................................................................................................................7


Update lib/[Link] ............................................................................................................................7

Handle Upload Errors ...........................................................................................................................8

STEP 4: Image Processing with Sharp ..................................................................................................9


Create lib/[Link]................................................................................................................9

Update Upload Route with Processing ..............................................................................................10

STEP 5: Save Avatar to User Profile ...................................................................................................11


Update Prisma Schema ......................................................................................................................11

Update Upload Route to Save Avatar ................................................................................................11

STEP 6: Serve Uploaded Files ............................................................................................................ 13


Serve Static Files ................................................................................................................................13

Add Avatar URL to User Response .....................................................................................................13

Testing with Postman/HTTPie ........................................................................................................... 14


Using HTTPie ......................................................................................................................................14

Using cURL .........................................................................................................................................14

Postman Setup ...................................................................................................................................14

Troubleshooting ............................................................................................................................... 15

Final Project Structure ...................................................................................................................... 16


Part 4: Image & File Uploads | NodeJS Backend Lab

What You Will Learn


In this lesson, you will add image upload functionality to your API. By the end, you will be able to:

• Upload images using Multer middleware

• Validate file types (images only) and size limits

• Resize images using Sharp for thumbnails

• Save file paths to the database

• Serve uploaded files statically

Prerequisites:Part 3 (Authentication) with working User model and JWT authentication.

3 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab

STEP 1: Install Multer & Sharp


Install the required packages for file handling and image processing:

npm install multer sharp


npm install --save-dev @types/multer

What was installed?Multer handles multipart/form-data (file uploads). Sharp is a fast image resizing
library.

Create Upload Directory


Create a folder to store uploaded files:

mkdir uploads
mkdir uploads/avatars
mkdir uploads/thumbnails

4 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab

STEP 2: Basic File Upload Setup


Create a reusable Multer configuration:

Create lib/[Link]
// File: lib/[Link]

const multer = require('multer');


const path = require('path');

// Configure storage
const storage = [Link]({
destination: (req, file, cb) => {
cb(null, 'uploads/avatars/');
},
filename: (req, file, cb) => {
// Create unique filename: [Link]
const uniqueSuffix = [Link]() + '-' + [Link]([Link]() * 1E9);
const ext = [Link]([Link]);
cb(null, `avatar-${uniqueSuffix}${ext}`);
}
});

// Create multer instance


const upload = multer({ storage });

[Link] = { upload };

Add Upload Endpoint


Create a new route for avatar uploads:

File: routes/[Link]

const express = require('express');


const router = [Link]();
const { upload } = require('../lib/upload');
const { requireAuth } = require('../middleware/auth');

// POST /api/uploads/avatar
// Single file upload with field name 'avatar'
[Link]('/avatar',
requireAuth,

5 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab
[Link]('avatar'),
(req, res) => {
if (![Link]) {
return [Link](400).json({ error: 'No file uploaded' });
}

[Link]({
message: 'Avatar uploaded successfully',
filename: [Link],
path: [Link],
size: [Link]
});
}
);

[Link] = router;

Update [Link]
const uploadRoutes = require('./routes/uploads');
[Link]('/api/uploads', uploadRoutes);

6 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab

STEP 3: File Validation


Add validation for file type and size:

Update lib/[Link]
// File: lib/[Link] (updated with validation)

const multer = require('multer');


const path = require('path');

// Allowed file types


const ALLOWED_TYPES = /jpeg|jpg|png|gif|webp/;

// Max file size: 5MB


const MAX_SIZE = 5 * 1024 * 1024;

const storage = [Link]({


destination: (req, file, cb) => {
cb(null, 'uploads/avatars/');
},
filename: (req, file, cb) => {
const uniqueSuffix = [Link]() + '-' + [Link]([Link]() * 1E9);
const ext = [Link]([Link]).toLowerCase();
cb(null, `avatar-${uniqueSuffix}${ext}`);
}
});

// File filter for type validation


const fileFilter = (req, file, cb) => {
const extname = ALLOWED_TYPES.test(
[Link]([Link]).toLowerCase()
);
const mimetype = ALLOWED_TYPES.test([Link]);

if (extname && mimetype) {


return cb(null, true);
} else {
cb(new Error('Only image files (jpeg, jpg, png, gif, webp) are allowed'));
}
};

const upload = multer({

7 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab
storage,
fileFilter,
limits: { fileSize: MAX_SIZE }
});

[Link] = { upload };

Handle Upload Errors


// Update routes/[Link] with error handling

const handleUploadError = (err, req, res, next) => {


if (err instanceof [Link]) {
// Multer-specific errors
if ([Link] === 'LIMIT_FILE_SIZE') {
return [Link](400).json({
error: 'File too large. Max size is 5MB.'
});
}
return [Link](400).json({ error: [Link] });
}

if (err) {
return [Link](400).json({ error: [Link] });
}

next();
};

[Link]('/avatar',
requireAuth,
[Link]('avatar'),
handleUploadError,
(req, res) => {
// ... response
}
);

8 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab

STEP 4: Image Processing with Sharp


Automatically resize uploaded images to create thumbnails:

Create lib/[Link]
// File: lib/[Link]

const sharp = require('sharp');


const path = require('path');

async function createThumbnail(inputPath, width = 200, height = 200) {


const filename = [Link](inputPath, [Link](inputPath));
const outputPath = `uploads/thumbnails/${filename}-[Link]`;

await sharp(inputPath)
.resize(width, height, {
fit: 'cover',
position: 'center'
})
.jpeg({ quality: 80 })
.toFile(outputPath);

return outputPath;
}

async function resizeImage(inputPath, maxWidth = 1200) {


const filename = [Link](inputPath);
const outputPath = `uploads/avatars/resized-${filename}`;

await sharp(inputPath)
.resize(maxWidth, null, {
withoutEnlargement: true
})
.jpeg({ quality: 85 })
.toFile(outputPath);

return outputPath;
}

[Link] = { createThumbnail, resizeImage };

9 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab

Update Upload Route with Processing


// File: routes/[Link] (updated)

const { createThumbnail, resizeImage } = require('../lib/imageProcessor');

[Link]('/avatar',
requireAuth,
[Link]('avatar'),
handleUploadError,
async (req, res) => {
try {
if (![Link]) {
return [Link](400).json({ error: 'No file uploaded' });
}

// Process images
const thumbnailPath = await createThumbnail([Link], 150, 150);
const resizedPath = await resizeImage([Link], 800);

[Link]({
message: 'Avatar uploaded and processed',
original: [Link],
thumbnail: [Link](thumbnailPath),
resized: [Link](resizedPath),
size: [Link]
});
} catch (error) {
[Link]('Image processing error:', error);
[Link](500).json({ error: 'Image processing failed' });
}
}
);

10 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab

STEP 5: Save Avatar to User Profile


Update the User model and save avatar URL to database:

Update Prisma Schema


// Add to prisma/[Link]

model User {
id Int @id @default(autoincrement())
email String @unique
name String
role String @default('student')
passwordHash String
avatar String? // NEW: Avatar filename (optional)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@@map('users')
}

// Run migration
npx prisma migrate dev --name add_user_avatar

Update Upload Route to Save Avatar


// File: routes/[Link]

const prisma = require('../lib/prisma');

[Link]('/avatar',
requireAuth,
[Link]('avatar'),
handleUploadError,
async (req, res) => {
try {
if (![Link]) {
return [Link](400).json({ error: 'No file uploaded' });
}

// Process image
const thumbnailPath = await createThumbnail([Link], 150, 150);

// Update user avatar in database

11 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab
const user = await [Link]({
where: { id: [Link] },
data: { avatar: [Link] },
select: { id: true, name: true, email: true, avatar: true }
});

[Link]({
message: 'Avatar updated successfully',
user
});
} catch (error) {
[Link]('Upload error:', error);
[Link](500).json({ error: 'Upload failed' });
}
}
);

12 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab

STEP 6: Serve Uploaded Files


Make uploaded files accessible via URL:

Serve Static Files


// File: [Link]

const path = require('path');

// Serve uploads folder statically


[Link]('/uploads', [Link]([Link](__dirname, 'uploads')));

// Now files are accessible at:


// [Link]

Add Avatar URL to User Response


// File: routes/[Link]

const BASE_URL = [Link].BASE_URL || '[Link]

// Helper to add avatar URL


function addAvatarUrl(user) {
return {
...user,
avatarUrl: [Link] ? `${BASE_URL}/uploads/avatars/${[Link]}` : null
};
}

// In GET /api/users/:id
[Link]('/:id', requireAuth, async (req, res) => {
const user = await [Link]({
where: { id: parseInt([Link]) },
select: { id: true, name: true, email: true, avatar: true, role: true }
});

if (!user) {
return [Link](404).json({ error: 'User not found' });
}

[Link](addAvatarUrl(user));
});

13 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab

Testing with Postman/HTTPie

Using HTTPie
# Upload avatar (requires auth token)
http -f POST :3000/api/uploads/avatar \
Authorization:'Bearer <your_token>' \
avatar@~/Pictures/[Link]

Using cURL
curl -X POST [Link] \
-H 'Authorization: Bearer <your_token>' \
-F 'avatar=@/path/to/[Link]'

Postman Setup
1. Set method to POST

2. URL: [Link]

3. Headers: Authorization: Bearer <token>

4. Body: Select 'form-data'

5. Key: avatar (type: File)

6. Value: Select your image file

14 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab

Troubleshooting
Error: 'Cannot find module multer'

Fix:Multer not installed. Run: npm install multer

Error: 'Unexpected field'

Fix:The field name in form doesn't match. Ensure field name is 'avatar' in your form/Postman

Error: 'File too large'

Fix:File exceeds 5MB limit. Resize image or increase MAX_SIZE in [Link]

Images not accessible via URL

Fix:Check that [Link]('/uploads', [Link](...)) is before your routes

Sharp installation fails

Fix:Sharp requires native dependencies. On Mac: brew install vips. On Ubuntu: sudo apt install
libvips-dev

15 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab

Final Project Structure


backend-lab/
├── uploads/
│ ├── avatars/ # Original uploaded avatars
│ └── thumbnails/ # Generated thumbnails
├── lib/
│ ├── [Link]
│ ├── [Link]
│ ├── [Link] # NEW: Multer config
│ └── [Link] # NEW: Sharp image processing
├── routes/
│ ├── [Link]
│ ├── [Link]
│ └── [Link] # NEW: Upload routes
├── middleware/
│ └── [Link]
├── prisma/
│ └── [Link] # Updated with avatar field
├── [Link] # Added static file serving
└── [Link]

Success!Your API now supports image uploads with validation and processing.

Next Steps:Cloud storage (AWS S3), multiple file uploads, or delete old avatars on update.

16 / 17
Part 4: Image & File Uploads | NodeJS Backend Lab

Backend Development Lab

Part 4: Image & File Uploads

Quick Step-by-Step Guide

17 / 17

You might also like