In Angular 6, after POSTing big file in Mozilla RAM usage skyrockets

Viewed 264

I have an Angular 6 app that uploads one file using POST:

submit-form.component.html

<input type="file" id="file" (change)="onFileChange($event.target.files)">
<button (click)="uploadFile()"> Upload </button>

submit-form.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpResponse, HttpEventType } from '@angular/common/http';

import { FileService } from '../file.service';

@Component({
    selector: 'app-submit-form',
    templateUrl: './submit-form.component.html',
    styleUrls: ['./submit-form.component.css']
})
export class SubmitFormComponent implements OnInit {
    constructor( private fileService: FileService) { }

    file_to_upload: File;

    onFileChange(files: FileList) {
        this.file_to_upload = files.item(0);
    }

    uploadFile() {
        this.fileService.uploadFile(this.file_to_upload).subscribe(
            (event) => {
                if (event.type == HttpEventType.UploadProgress) {
                    const percentDone = Math.round(100 * event.loaded / event.total);
                    console.log(`Uploading - %${percentDone}...`);
                } else if (event instanceof HttpResponse) {
                    console.log('File completely loaded!');
                }
            },
            (err) => {
                console.log('Upload Error', JSON.stringify(err));
            }, () => {
                console.log('Done uploading file!');
            }
        );
    }
}

file.service.ts

import { Injectable } from '@angular/core';

import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
    providedIn: 'root'
})
export class FileService {
    private uploadUrl = 'http://localhost:4200/upload';
    constructor(private http: HttpClient) { }

    uploadFile(file: File): Observable<any> {
        var formData = new FormData();
        formData.append('file_to_upload', file, file.name);

        var params = new HttpParams();
        var httpOptions = {
            params: params,
            reportProgress: true
        };

        const req = new HttpRequest('POST', this.uploadUrl, formData, httpOptions);
        return this.http.request(req);
    }
}

And Node.JS server that saves that file using multer:

server.js

const http = require('http')
const url = require('url')
const path = require('path')
const multer = require('multer')
const express = require('express')

const router = express()
const serverPort = 4200;

router.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
    next();
});

var storage = multer.diskStorage({
    destination: (req, file, cb) => cb(null, 'data/upload/'),
    filename: (req, file, cb) => {
        console.log('Upload file ', file)
        cb(null, file.originalname)
    }
});
var upload = multer({storage: storage});


router.post('/upload', upload.single('file_to_upload'), (req, res) => {
    res.json({'Code': 200, 'Message': 'Success'});
});

router.listen(serverPort, () => console.log(`Server running at http://localhost:${serverPort}/`));

On Mozilla it works perfectly with small files (<500MB), but when I upload something bigger, the browser freezes between Uploading - 100% and File completely loaded!, rapidly raises it's memory consumption by approximately 1.5x file size and then instantly drops back down, outputting File completely loaded! and Done uploading file! (judging by data/upload/ folder, the file finishes uploading somewhere at the beginning of a memory spike). On Chrome file size does not matter - it always works properly (even with >3GB files).

If I use HTML's <form> for file upload, like this:

<form action="http://localhost:4200/upload" method="POST" enctype="multipart/form-data">
    <input type="file" name="file_to_upload" >
    <input type="submit" value="Upload">
</form>

...then in both browsers there are no sudden memory spikes. So, what's going on?

0 Answers
Related