How to download a pdf file through javascript?

2019-03-01 02:52发布

问题:

My javascript code makes the following AJAX request to my node.js server:

var url = '/node/download';
var downloadRequest = new goog.net.XhrIo();
downloadRequest.headers.set('content-type', 'application/json');
downloadRequest.send(url);

My node.js server creates a pdf at the node and streams the pdf back to the client via the following code:

    var filestream = fs.createReadStream(pdfpath);                  
    res.writeHead(200, {
        'Content-disposition': 'attachment; filename=' + filename,
        "Content-Type":"application/pdf","Content-Transfer-Encoding": "binary"});
    filestream.on('data', function(chunk) {                     
        res.write(chunk);
    });
    filestream.on('end', function() {
        res.end();
    });

But now I am having trouble at how to receive this response back at the javascript client so that a download prompt will open to allow the user to download and save the pdf file.

Please help!

Thanx in advance!

P.S. Plz also suggest any better way to implement my node's code(if there is any)

Edit: One possible solution would be to send my request like this:

window.location.assign('/node/download');

This way i get the download prompt and everything works fine except that the asynchronous nature of the product is sacrificed. Is there a work around for this so that I can also retain asynchronicity?

回答1:

For downloading a pdf file saved on the server

Make the request like this from the client javascript:

var reqObj = new XMLHttpRequest();
reqObj.open('GET','getpdf',true);     // 'getpdf' is the URI to recongize your request at the server
reqObj.send();

reqObj.onreadystatechange = function() {
    var resObj = this;
    if(resObj.readyState == resObj.DONE) {
        if (resObj.status != 200) {
            console.log("pdf can't be downloaded");
        } else if (resObj.status == 200){
            var resTxt = reqObj.responseText;
            window.location.assign(resTxt);    // Opens the pdf download prompt
        }
    }
}

At the node handle the request received from above and respond:

var http = require('http');

function getPDFUrl() {
    return "http://testing.com/pdf/test.pdf";
}

var handler = http.createServer(function(request, response) {
if (request.url == 'getpdf' && request.method.toLowerCase() == 'get') {
    var pdfUrl = getPDFUrl();       //get pdf url here

    if (pdfUrl != null && pdfUrl != undefined && pdfUrl != '') {
        response.writeHead(200, {"Content-Type":"text/html"});
        response.write(pdfUrl);
        response.end();
    } else {
        response.writeHead(404, {"Content-Type":"text/html"});
        response.write("Not Found");
        response.end();
    }

}
});


回答2:

I implement similar async file generation features in some apps. The approach I take is a little more involved, but keeps your interface async.

  • Client sends a request for the file to be generated.
  • Server sends response with the URL for the generated file.
  • Client makes a second request to download the generated file.

This is invisible to the user, they will just need to wait for the second transaction to come back.