我有一个Angular 6应用,该应用使用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);
}
}
以及使用multer保存该文件的Node.JS服务器:
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}/`));
在Mozilla上,它可以很好地处理较小的文件(<500MB),但是当我上传更大的文件时,浏览器冻结在Uploading - 100%
和File completely loaded!
之间,从而使内存消耗迅速增加了大约1.5倍文件大小然后立即回落,输出File completely loaded!
和Done uploading file!
(从data/upload/
文件夹判断,该文件在内存峰值开始时完成了上载)。在Chrome上,文件大小无关紧要-始终可以正常运行(即使使用大于3GB的文件也是如此)。
如果我使用HTML的<form>
上传文件,就像这样:
<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>
...然后在两个浏览器中都没有突然的内存高峰。那么,这是怎么回事?