从 MongoDB 下载文件时在 Chrome 中获取 "Failed - File incomplete"

Getting "Failed - File incomplete" in Chrome when downloading file from MongoDB

我的 JavaScript 应用程序允许用户下载文件。该页面显示文件的可点击 link。该文件存储在 MongoDB 中。当我单击 link 下载文件时,我在 Chrome 中收到“失败 - 文件不完整”。文件下载应该显示在我的下载文件中,但它没有。我不知道出了什么问题,我希望这里的人能对这个问题有所了解。

此应用是使用 node/express/ejs/MongoDB

构建的

这是路由器代码:

router.get('/:id/download', async (req, res) => {

    try {

        const bug = await Bug.findById(req.params.id)
        let buf = Buffer.from(bug.files)

        res.writeHead(200, {
            'Content-Disposition': `attachment; filename="${bug.fileName}"`,
            'Content-Type': bug.fileType,
            'Content-Length': buf.length,
        }).end()

        fs.writeFile(bug.fileName, buf, (err) => {
            if (err) {
                console.log(err);
            }
            else {
                console.log("File written successfully\n");
            }
        })

    } catch (err) {
        console.log("error downloading file", err)
    }

    res.end()
})

这是 HTML:

<div class="container-sm mt-5">
    <div class="row">
        <div class="col-lg-3"></div>
            <div class="col-lg-6">
                <h2>Bug Details</h2>
                <p>Title: <%= bug.title %></p>
                <p>Description: <%= bug.description %></p>
                <p>Category: <%= bug.category %></p>
                <p>Status: <%= bug.status %></p>
                <p>Priority: <%= bug.priority %></p>
                <p>Supporting Documents: </p>
                <a href="/<%= bug.id %>/download"><%= bug.fileName %></a>
                <div>
                <a href="/<%= bug.id %>/edit">Edit</a>
                <form class="mt-3" method="POST" action="/<%= bug.id %>?_method=DELETE">
                    <button type="submit">Delete</button>
                </form>
            </div>
            </div>
        <div class="col-lg-3"></div>
    </div>
</div>

在 MongoDB 中,文件存储为文档的一部分:

files: {
        type: Buffer,
        required: false
    },

    fileName: {
        type: String,
        required: false
    },

    fileType: {
        type: String,
        required: false
    },

    fileSize: {
        type: Number,
        required: false
    }

当我使用虚拟 .txt 文件进行测试时,Chrome 开发工具将响应 header 显示为:

HTTP/1.1 200 OK X-Powered-By: Express Content-Disposition: attachment; filename="dummyfile.txt" Content-Type: text/plain Content-Length: 9 Date: Fri, 06 May 2022 20:19:01 GMT Connection: keep-alive Keep-Alive: timeout=5

一个有趣的旁注:该文件确实下载到我的项目文件夹中并且一切正常,但它没有按应有的方式下载到我的 /downloads 文件夹中。

你应该使用express提供的res.download方法,不需要设置任何headers。

此外,我正在使用 fs promises 模块来实现异步等待语法

const fs = require("fs").promises;

router.get("/:id/download", async (req, res) => {
  try {
    const bug = await Bug.findById(req.params.id);
    let buf = Buffer.from(bug.files);
    await fs.writeFile(bug.fileName,buf);

    res.download(bug.fileName, err => {
      if (err) {
        throw err;
      } else {
        // If download is complete
        if (res.headersSent) {
          // if you want to delete the file which was created locally after download is complete
          fs.rm(bug.fileName);
        }
      }
    });
  } catch (err) {
    console.log("error downloading file", err);
  }
});