简体   繁体   中英

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

My JavaScript application allows users to download a file. The page shows a clickable link to the file. The file is stored in MongoDB. When I click on the link to download the file, I'm getting "Failed - File incomplete" in Chrome. The file download should show up in my downloads file, but it doesn't. I don't know what is wrong and I hope someone here can shed some light on the problem.

This app is built using node/express/ejs/MongoDB

Here's the router code:

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()
})

Here's the 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>

In MongoDB the file is stored as part of a document:

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

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

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

    fileSize: {
        type: Number,
        required: false
    }

When I test using a dummy.txt file, Chrome dev tools shows the response header as:

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

One interesting side note: The file does download into my projects folder and everything is fine, but it doesn't download to my /downloads folder as it should.

You should use res.download method which express provides, no need to set any headers.

Also, I'm using fs promises module for async await syntax

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);
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM