简体   繁体   中英

How to send PDF file to frontend?

I have a saved .PDF file on my system, and I am trying to send the file to the frontend using node/express.

I'm getting the file to send to the frontend as a stream (binary string), but when running some code on the frontend to get the .PDF to download onto the users computer, the .PDF file shows up blank.

Here is my route on the server:

app.post('/someroute', (req, res) => {
  let pdfPath = './somepath/where/the/pdf/is'
  // if the file does not exist
  if (!fs.existsSync(pdfPath)) {
    console.log(`The PDF does NOT exist @ ${pdfPath}`)
    return res.json({ success: false });
  }

  res.download(pdfPath, (err) => {
    if (err) {
      console.log('there was error in res.downoad!', err)
    } else {
      fs.unlink(pdfPath, (err) => {
        if (err) {
          console.log('there was error in unlinking the pdf file!', err)
        } else {
          console.log('success!')
        }
      })
    }
  })
})

Here is the code on the frontend:

$.post("/someroute", function(data) {
    console.log('creating PDF...', data)

    var downloadLink = document.createElement('a')
    downloadLink.target = '_blank'
    downloadLink.download = 'new_pdf_haha.pdf'
    var blob = new Blob([data], { type: 'application/pdf' })
    var URL = window.URL || window.webkitURL
    var downloadUrl = URL.createObjectURL(blob)
    // set object URL as the anchor's href
    downloadLink.href = downloadUrl
    // append the anchor to document body
    document.body.append(downloadLink)
    // fire a click event on the anchor
    downloadLink.click()
    // cleanup: remove element and revoke object URL
    document.body.removeChild(downloadLink)
    URL.revokeObjectURL(downloadUrl)
  })

Here is the stream i'm receiving on the frontend: stream on the frontend

Here is the PDF i'm expecting to be downloaded on the frontend:

预期PDF

Here is what's actually being downloaded:

实际下载的PDF

If anyone can lend any insight or help it would be very much appreciated, thanks!

I think the main reason this isn't working for you is because jQuery doesn't support the 'blob' data type.

I did some research and found an example of how to get this to work with jQuery:

http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/

You need to include the jQuery plugin from the blog post then convert your $.post call to a $.ajax call (with method POST) and specify that the transfer data type be 'binary' (to load the plugin).

After including the plugin, change your code to look like this:

    $.ajax({
            method: "POST",
            url: "/someroute",
            dataType: 'binary' // USE THE PLUGIN
        })
        .then(function (data) {
            console.log("Got the PDF file!");

            // Do with the PDF data as you please.

            var downloadLink = document.createElement('a')
            downloadLink.target = '_blank'
            downloadLink.download = 'new_pdf_haha.pdf'
            var blob = new Blob([data], { type: 'application/pdf' })
            var URL = window.URL || window.webkitURL
            var downloadUrl = URL.createObjectURL(blob)
            downloadLink.href = downloadUrl
            document.body.append(downloadLink) // THIS LINE ISN'T NECESSARY
            downloadLink.click()
            document.body.removeChild(downloadLink);  // THIS LINE ISN'T NECESSARY
            URL.revokeObjectURL(downloadUrl);
        })
        .catch(function (err) {
            console.error("An error occurred.");
            console.error(err);
        });

There's a full working example for you here:

https://github.com/ashleydavis/pdf-server-example

Note that my server setup is different to yours, that may or may not be an issue for you. I have included example code for streaming and non-streaming PDF file download for comparison - streaming is used by default because I think that's what you wanted.

Also note that it does not appear necessary to add your synthesized link to the document and I have marked those lines as unnecessary.

I should also note that it is probably best to do this kind of thing with HTTP GET rather than HTTP POST. If you did that you could simplify your browser download code to be the following:

        var downloadLink = document.createElement('a');
        downloadLink.target = '_blank';
        downloadLink.download = 'new_pdf_haha.pdf';
        downloadLink.href = "someroute";
        document.body.append(downloadLink)
        downloadLink.click()
        document.body.removeChild(downloadLink);

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