Basic HTTP Server with File Upload
In this project, we'll build a basic HTTP server that can handle file uploads – all without using Express! This will give you a deeper understanding of how web servers handle multipart form data and file streaming.
Project Overview: File Upload Server
We'll create a server that:
- Serves an HTML form for uploading files.
- Handles POST requests with file uploads.
- Saves uploaded files to a local folder.
- Lists uploaded files and allows viewing them.
This project uses the `http`, `fs`, `path`, and `url` modules. We'll also work with streams to handle file data efficiently.
Step 1: Setup and Folder Structure
mkdir file-upload-servercd file-upload-servernpm init -ymkdir public uploadsStep 2: Create the HTML Upload Form
Create `public/index.html`:
<!DOCTYPE html><html><head> <title>File Upload</title></head><body> <h1>Upload a File</h1> <form action="/upload" method="POST" enctype="multipart/form-data"> <input type="file" name="myfile" > <button type="submit">Upload</button> </form></body></html>Step 3: Create the Server (server.js)
const http = require('http');const fs = require('fs');const path = require('path');const url = require('url');
const server = http.createServer((req, res) => { const parsedUrl = url.parse(req.url, true); const pathname = parsedUrl.pathname; <!-- Serve the upload form --> if (pathname === '/' && req.method === 'GET') { const filePath = path.join(__dirname, 'public', 'index.html'); fs.readFile(filePath, (err, content) => { if (err) { res.writeHead(500); res.end('Server Error'); } else { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(content); } }); } <!-- Handle file upload --> else if (pathname === '/upload' && req.method === 'POST') { const contentType = req.headers['content-type']; if (!contentType || !contentType.includes('multipart/form-data')) { res.writeHead(400); return res.end('Bad Request: expected multipart/form-data'); } <!-- Parse boundary from content-type header --> const boundary = contentType.split('boundary=')[1]; <!-- We'll collect the raw data and parse it manually (simplified) --> let rawData = []; req.on('data', chunk => rawData.push(chunk)); req.on('end', () => { const buffer = Buffer.concat(rawData); <!-- Very simplified parsing – in real app use a library like `busboy` or `multer` --> <!-- For demo, we'll just save the whole body as a file (not correct, but shows concept) --> const filename = 'upload_' + Date.now() + '.dat'; const savePath = path.join(__dirname, 'uploads', filename); fs.writeFile(savePath, buffer, (err) => { if (err) { res.writeHead(500); return res.end('Error saving file'); } res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(`<h1>File uploaded successfully!</h1><a href="/">Go back</a>`); }); }); } <!-- Serve uploaded files --> else if (pathname.startsWith('/uploads/') && req.method === 'GET') { const filename = pathname.split('/')[2]; const filePath = path.join(__dirname, 'uploads', filename); fs.readFile(filePath, (err, content) => { if (err) { res.writeHead(404); res.end('File not found'); } else { res.writeHead(200); res.end(content); } }); } <!-- 404 --> else { res.writeHead(404); res.end('404 Not Found'); }});
const PORT = process.env.PORT || 3000;server.listen(PORT, () => { console.log(`Server running at http://localhost:${PORT}/`);});Step 4: Using a Proper Multipart Parser (Optional Enhancement)
Parsing multipart data manually is complex. In a real project, you'd use a library like `busboy` or `multer`. But for learning, our simplified version shows the concept.
Running the Server
node server.jsOpen your browser to `http://localhost:3000`, upload a file, and see it saved in the `uploads` folder.
Two Minute Drill
- We built a basic HTTP server that handles file uploads using only built-in modules.
- Served an HTML form for file selection.
- Handled POST requests with `multipart/form-data` encoding.
- Saved uploaded files to disk using `fs.writeFile`.
- Served uploaded files via a `/uploads` route.
- This project demonstrates real-world server concepts: routing, file I/O, and multipart form handling.
Need more clarification?
Drop us an email at career@quipoinfotech.com
