使用临时文件在express.js服务器上上传多个文件

时间:2019-02-04 23:02:20

标签: node.js express file-upload

我有一个简单的express.js服务器和Angular7前端应用程序(MEAN堆栈)。在某个页面上,我想允许用户上传多个文件。为了在服务器端上传文件,我正在使用express-fileupload节点程序包。 Angular端工作得很好,它可以正确发送文件,经过103%的测试。但是,快递方面给我带来了一些困难。

因此,我现在至少搜索了3天,似乎没有任何解决办法。首先,让我详细介绍一下我在做什么:

正如我所说,在角度方面,一切都很好。在服务器端,要设置文件上传库,我正在app.js中进行此操作:

import fileupload from "express-fileupload";
...
app.use
(
    fileupload
    ({
        createParentPath: true,
        limits: { fileSize: 25 * 1024 * 1024 },
        useTempFiles: true,
        tempFileDir: "\\..\\..\\..\\tmp\\", // don't mind this, just temporary storing files here while developing, practical reasons
        safeFileNames: true,
        preserveExtension: 10,
        abortOnLimit: true,
        parseNested: true
    })
);

之后,我在“ / dev”子位置上有一个路由器,这导致了这一点:

import express from "express";
import fileupload from "express-fileupload";
import path from "path";
...
let router = express.Router();
...
router.post("/upload", (req, res, next) =>
{
    let code: number = 200;
    let response =
    {
        result: "danger",
        message: "Could not upload file(s)."
    };

    if (req.files)
    {
        // since angular is sending the files with names 'files[0]', 'files[1]', ... (see below), and since 'parseNested' is true
        // (from the documentation on the link I provided above, it will compress all files in one array whose name is just 'files', so this cast is ok
        let uploads = <{ files: fileupload.UploadedFile[] }>req.files;
        let success = true;

        for (let i = 0; i < uploads.files.length; ++i)
        {
            uploads.files[i].mv(path.join(__dirname, "../../images/", uploads.files[i].name), err => success = err ? false : success);
        }

        if (success)
        {
            response.result = "success";
            response.message = "Files were uploaded successfully.";
        }
    }

    return res.status(code).json(response);
});

在角度上,我正在发送如下文件:

import { HttpClient } from "@angular/common/http";
...
public constructor(private http: HttpClient) { }
...
// 'files' is coming from <input type="file" ...> html element, and the callback is not important
upload(files: FileList, callback: CallbackFunction)
{
    let form: FormData = new FormData();
    for (let i = 0; i < files.length; ++i)
        form.append("files[" + i + "]", files[i], files[i].name);

    this.http.post("/dev/upload", form).subscribe(callback);
}

现在,这是正在发生的奇怪的事情。当我仅上传1个文件时,此代码完全可以正常工作。但是,如果我在元素中选择了多个文件,则会弹出此异常(在服务器上)并关闭服务器:

Error [ERR_STREAM_WRITE_AFTER_END]: write after end
    at writeAfterEnd (_stream_writable.js:248:12)
    at WriteStream.Writable.write (_stream_writable.js:296:5)
    at FileStream.<anonymous> (D:\Desktop\projects\job-fair\src\jf-backend\node_modules\express-fileupload\lib\tempFileHandler.js:32:17)
    at FileStream.emit (events.js:182:13)
    at addChunk (_stream_readable.js:287:12)
    at readableAddChunk (_stream_readable.js:268:11)
    at FileStream.Readable.push (_stream_readable.js:223:10)
    at PartStream.onData (D:\Desktop\projects\job-fair\src\jf-backend\node_modules\busboy\lib\types\multipart.js:223:28)
    at PartStream.emit (events.js:182:13)
    at addChunk (_stream_readable.js:287:12)
    at readableAddChunk (_stream_readable.js:268:11)
    at PartStream.Readable.push (_stream_readable.js:223:10)
    at Dicer._oninfo (D:\Desktop\projects\job-fair\src\jf-backend\node_modules\dicer\lib\Dicer.js:191:36)
    at SBMH.<anonymous> (D:\Desktop\projects\job-fair\src\jf-backend\node_modules\dicer\lib\Dicer.js:127:10)
    at SBMH.emit (events.js:182:13)
    at SBMH._sbmh_feed (D:\Desktop\projects\job-fair\src\jf-backend\node_modules\streamsearch\lib\sbmh.js:188:10)
    at SBMH.push (D:\Desktop\projects\job-fair\src\jf-backend\node_modules\streamsearch\lib\sbmh.js:56:14)
    at Dicer._write (D:\Desktop\projects\job-fair\src\jf-backend\node_modules\dicer\lib\Dicer.js:109:17)
    at doWrite (_stream_writable.js:415:12)
    at writeOrBuffer (_stream_writable.js:399:5)
    at Dicer.Writable.write (_stream_writable.js:299:11)
    at Multipart.write (D:\Desktop\projects\job-fair\src\jf-backend\node_modules\busboy\lib\types\multipart.js:290:24)
Emitted 'error' event at:
    at errorOrDestroy (internal/streams/destroy.js:98:12)
    at writeAfterEnd (_stream_writable.js:250:3)
    at WriteStream.Writable.write (_stream_writable.js:296:5)
    [... lines matching original stack trace ...]
    at Dicer.Writable.write (_stream_writable.js:299:11)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! jf-backend@0.0.0 start: `tsc&node ./bin/www`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the jf-backend@0.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\vladi\AppData\Roaming\npm-cache\_logs\2019-02-04T21_51_27_602Z-debug.log

当我这样做时,要变得更奇怪:

import fileupload from "express-fileupload";
...
app.use
(
    fileupload
    ({
        createParentPath: true,
        limits: { fileSize: 25 * 1024 * 1024 },
        //useTempFiles: true,
        //tempFileDir: "\\..\\..\\..\\tmp\\",
        safeFileNames: true,
        preserveExtension: 10,
        abortOnLimit: true,
        parseNested: true
    })
);

即使我上传多个文件,也不会使用相同的代码引发异常。因此,看起来,如果我不使用临时文件和tmp dir,则上传工作正常,我尝试上传5-6个文件(我的用例对此不多),它可以完美运行。我唯一可以得出的假设是,代表该库存在一些错误。我的意思是,因为我没有上传大型文件,也没有上传一大堆文件,所以我不使用临时文件是可以的。但是,我仍然对问题可能是什么以及是否有正确解决此问题的修补程序或解决方法感到好奇。

0 个答案:

没有答案