Loading

Quipoin Menu

Learn • Practice • Grow

node-js / Basic HTTP Server with File Upload
tutorial

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-server
cd file-upload-server
npm init -y
mkdir public uploads

Step 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.js

Open 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