【问题标题】:Simple Node.js program hogging all system memory and taking forever writing XMLHttpRequest file buffer to disk简单的 Node.js 程序占用所有系统内存并永远将 XMLHttpRequest 文件缓冲区写入磁盘
【发布时间】:2017-06-19 07:24:19
【问题描述】:

我创建了一个文件共享应用程序以在我的家庭网络上使用。它有点类似于 Google Drive 或 Dropbox 的网络界面,但没有任何文件大小上限且没有安全性。

当从通过 LAN 连接的其他计算机立即传输小文件时,它可以完美运行,但是在对 2GB 文件进行测试时发生了一些奇怪的事情。

在我将其切断之前,进度条大约需要四个小时才能达到 50%。另外,看看 Node 使用了多少内存。

它会从低容量开始逐步增加到 13GB,然后转储并重新启动,每分钟数次。

文件是使用 XMLHttpRequest 从浏览器界面上传的。这是前端代码必不可少的部分。

var formData = new FormData();
var file = document.getElementById("fileinput").files[0];
formData.append("file", file);

var xhr = new XMLHttpRequest();
xhr.open("post", "/fileupload", true);
xhr.send(formData);

在服务器端有一个使用 express 的非常简单的处理程序,它接受 req.files.file 并将其直接传递到 fs.writeFile 以将其保存到磁盘。 (根据 console.log,'req.files.file' 似乎是 Buffer 类型,显然可以是 piped right onto disk)。

var express = require("express");
var fileUpload = require("express-fileupload");
var app = express();
app.use(express.static("public"));
app.use(fileUpload());
var fs = require("fs");

app.post('/fileupload', function(req, res) {
    if(req.files && req.files.file){
        var file = req.files.file;
        fs.writeFile("./public/shared/" + file.name, file.data, "binary", function(err) {
            if(err) {
                res.send(err);
                return;
            }
            res.send("File uploaded successfully.");
        }); 
    }
    else{
        res.send("No file was uploaded.");
        return;
    }
});

我正在使用express-fileupload 处理上传。

两台计算机都运行 Windows。发送计算机使用的是 Chrome。节点版本为 7.5.0。

我哪里出错了?我该如何解决这个问题?

【问题讨论】:

  • 您使用什么中间件来处理上传? multer?请分享它的初始化。
  • @SergeyLapin 我的错。应该包括该信息。我正在使用快速文件上传。我已经更新了我的问题。
  • 谢谢。我将在 GitHub here 上开源这个项目。

标签: javascript node.js express buffer


【解决方案1】:

对于大文件,您可能应该使用 writeStream 而不是 writeFile。 当你使用 writeFile 时,整个文件必须保存在内存中,因此内存消耗很大。

这是一个不错的简短教程:http://joshondesign.com/2014/06/25/nodestreamsareawesome

node.js 也有它的文档: https://nodejs.org/api/fs.html#fs_class_fs_writestream

【讨论】:

  • writeFile被执行的那一刻,所有的数据都已经在内存中了,因为有一个巨大的Buffer实例的引用。
  • @SergeyLapin 是吗?这些缓冲区如何工作?我过去没有使用过 HTTP 缓冲区,但我的假设是它是从客户端到服务器的持久流,直到整个缓冲区都被读取。没有解释为什么我的内存使用量超出了图表 (13GB),但我会试一试。
  • @JSideris 你能回答我对原帖的评论吗?
【解决方案2】:

看看express-fileupload source。当文件到达时,它会接收一个传入流并开始将其放入Buffer,即放入内存中。 完成后,您可以通过writeFile 将此内存缓冲区写入磁盘。

express-fileupload 无法避免将文件存储在内存中。考虑使用 multer 和它提供的 DiskStorage 选项:docs

【讨论】:

  • 太棒了。恭喜!
猜你喜欢
  • 1970-01-01
  • 2015-08-11
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多