While uploading a large file to server there is a very high chance of internet disconnection so giving a resumable option in upload will be very useful in uploading a large file to the server.

I have used the fs module of the node.js to upload file in the server.

import { Component, OnInit } from "@angular/core";
import { HttpClient, HttpHeaders, HttpRequest, HttpEventType } from "@angular/common/http";

declare const socket: any;
// const socket = io("http://localhost:3000");

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
  title = "resumeUpload-ui";
  selectedFile;
  fReader;
  name = "";
  uploadPercent;

  color = "primary";
  mode = "determinate";
  value = 50.25890809809;
  socket = 'http';
  constructor(private http: HttpClient) {}

  ngOnInit() {
   
  }

  goToLink(url: string){
    window.open(url, "_blank");
  }

  onFileSelect(event) {
    this.selectedFile = event.target.files[0];
    this.name = this.selectedFile.name;
    console.log(this.selectedFile);
  }

  resumableUpload() {
    let fileId = `${this.selectedFile.name}-${this.selectedFile.lastModified}`;
    let headers = new HttpHeaders({
      "size": this.selectedFile.size.toString(),
      "x-file-id": fileId,
      'name': this.name
    });

    this.http
      .get("http://localhost:3000/status", { headers: headers })
      .subscribe((res: any) => {
        console.log(JSON.stringify(res));
        if(res.status === 'file is present'){
          alert(res.status);
          return;
        }
        let uploadedBytes = res.uploaded;
        let headers2 = new HttpHeaders({
          "size": this.selectedFile.size.toString(),
          "x-file-id": fileId,
          "x-start-byte": uploadedBytes.toString(),
          'name': this.name
        });
        const req = new HttpRequest('POST', "http://localhost:3000/upload", this.selectedFile.slice(uploadedBytes, this.selectedFile.size +1 ),{
           headers: headers2,
          reportProgress: true
        });
        this.http.request(req)
          .subscribe(
            (res: any) => {
              if(res.type === HttpEventType.UploadProgress){
                this.uploadPercent = Math.round(100* uploadedBytes/this.selectedFile.size);
                console.log(this.uploadPercent);
                if(this.uploadPercent >= 100){
                  this.name = "";
                  this.selectedFile = null;
                }
              }else{
                console.log(JSON.stringify(res));
                if(this.uploadPercent >= 100){
                  this.name = "";
                  this.selectedFile = null;
                }
              }
            },
            err => {}
          );
      });
  }
}
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const fs = require('fs');
const socket = require('socket.io');
const socketUpload = require('./app.js')

const app = express();
app.use(cors({origin: '*'}));
app.use(bodyParser.urlencoded({ extended: true }));

const server = app.listen(3000,() => {
    console.log('Started in 3000');
});

const io = socket(server);

io.sockets.on('connection', (socket) => {
    console.log(`new connection id: ${socket.id}`);
    socketUpload(socket);
});

let uploads = {};

app.post('/upload', (req, res, next) => {
    let fileId = req.headers['x-file-id'];
    let startByte = parseInt(req.headers['x-start-byte'], 10);
    let name = req.headers['name'];
    let fileSize = parseInt(req.headers['size'], 10);
    console.log('file Size',fileSize, fileId, startByte);
    if(uploads[fileId] && fileSize == uploads[fileId].bytesReceived){
      res.end();
      return;
    }

    console.log(fileSize);

    if (!fileId) {
        res.writeHead(400, "No file id");
        res.end(400);
    }
    console.log(uploads[fileId]);
    if (!uploads[fileId]) 
        uploads[fileId] = {};

    let upload = uploads[fileId];

    let fileStream;

    if(!startByte){
        upload.bytesReceived = 0;
        let name = req.headers['name'];
        fileStream = fs.createWriteStream(`./name/${name}`, {
          flags: 'w'
        });
    }else{
        if (upload.bytesReceived != startByte) {
            res.writeHead(400, "Wrong start byte");
            res.end(upload.bytesReceived);
            return;
          }
          // append to existing file
          fileStream = fs.createWriteStream(`./name/${name}`, {
            flags: 'a'
          });
    }

    req.on('data', function(data) {
        //console.log("bytes received", upload.bytesReceived);
        upload.bytesReceived += data.length;
      });
  
      req.pipe(fileStream);
    
      // when the request is finished, and all its data is written
      fileStream.on('close', function() {
        console.log(upload.bytesReceived, fileSize);
        if (upload.bytesReceived == fileSize) {
          console.log("Upload finished");
          delete uploads[fileId];
    
          // can do something else with the uploaded file here
          res.send({'status': 'uploaded'});
          res.end();
        } else {
          // connection lost, we leave the unfinished file around
          console.log("File unfinished, stopped at " + upload.bytesReceived);
          res.writeHead(500, "Server Error");
          res.end();
        }
      });
    
      // in case of I/O error - finish the request
      fileStream.on('error', function(err) {
        console.log("fileStream error", err);
        res.writeHead(500, "File error");
        res.end();
      });
    
  });

  app.get("/", (req, res) => {
    res.send(
      `<h1 style='text-align: center'>
            Wellcome to FunOfHeuristic 
            <br><br>
            <b style="font-size: 182px;">😃👻</b>
        </h1>`
    );
  });

app.get('/status', (req, res) =>{
    //console.log('came');
    let fileId = req.headers['x-file-id'];
    let name = req.headers['name'];
    let fileSize = parseInt(req.headers['size'], 10);
    console.log(name);
    if(name){
      try{
        let stats = fs.statSync('name/' +  name);
        if(stats.isFile())
        {
          console.log(`fileSize is ${fileSize} and already uploaded file size ${stats.size}`);
          if(fileSize == stats.size){
            res.send({'status': 'file is present', "uploaded" : stats.size})
            return;
          }
          if(!uploads[fileId])
            uploads[fileId] = {}
          console.log(uploads[fileId]);
          uploads[fileId]['bytesReceived'] = stats.size;
          console.log(uploads[fileId], stats.size);
        }
      }catch(er){

      }
      
    }
    let upload = uploads[fileId];
    if(upload)
        res.send({"uploaded" : upload.bytesReceived});
    else
        res.send({"uploaded" : 0});
    
});

Source Code: https://github.com/funOfheuristic/ResumableFileUploader
Subscribe: https://www.youtube.com/channel/UCsy12h-0xK_UCJDIDDEe0zQ

#node.js #angular.js #angular #javascript #express

How to resumable File Upload in Angular and Node.js
35.65 GEEK