7

I'm submitting JSON data to a server. The server generates a PDF file and responds with the URL to that PDF file. I then make another request to the server to download the PDF file. To do the download, I create a hidden iframe and set the source the the PDF url. Note that I want the user's browser to stay on the same page and download in the background. More details about what I'm doing and the solution I went with can be found in this SO question.

Whenever I use this technique in Chrome, everything works fine. But looking at the chrome developer console, I see the error message Failed to load resource. Is there a way to do this differently so that I won't get these errors?

A very simple and working example of the problem in action can be seen on jsfiddle. Just click the Download PDF button and look at your Chrome console.

The code on that page looks like this:

$(document).ready( function() {
    var downloadFile = function(url){
        var iframe = $("iframe#download");
        if (!iframe.length) {
            iframe = $("<iframe id='download' style='display:none;'/>");
            $("body").append(iframe);
        }
        iframe.attr("src", url);
    };

    $("button").click(function() {    
        downloadFile("http://www.education.gov.yk.ca/pdf/pdf-test.pdf");
    });
});
Community
  • 1
  • 1
Tauren
  • 26,795
  • 42
  • 131
  • 167
  • 2
    If you take out the "display: none;" it works for me on Chrome Stable for Mac. I think it has something to do with the fact that Chrome is trying to open the PDF using a built-in PDF viewer. Maybe try changing the content-type of the response from application/pdf to application/octet-stream so that it will just treat it as a normal file and download it? – Riley Dutton Mar 07 '11 at 14:59

6 Answers6

4

Other respondents have suggested changing the content-type header, which should work just as well, but there's a specific response header for instructing the browser how to treat a file.

The following should force the pdf to be downloaded rather than displayed in the browser:

"Content-disposition: attachment; filename=[your file's name]"

R Hill
  • 1,744
  • 1
  • 22
  • 35
  • Thanks. I'll have to go back and check, but I believe I'm already doing this. – Tauren Apr 01 '11 at 05:25
  • For some reason, the technique I was using before stopped working for some of my downloads in Chrome, even though downloads continued working properly in Safari. This change happened sometime in the last week or so. Perhaps something changed in the latest Chrome version? Anyway, I discovered that I wasn't setting `Content-disposition` for everything, and once I added it, then the downloads started working again in Chrome. I was setting the content-type before, but adding the disposition made the difference. So I'm marking this solution as the answer. – Tauren Nov 04 '11 at 07:06
  • 1
    Just thought I'd mention a gotcha that got me. Make sure the 'attachment' part of the header comes before the 'filename' part i.e. it should read 'attachment; filename=wibble.txt' rather than 'filename=wibble.txt; attachment' – Gruff Bunny Oct 07 '13 at 11:54
2

This is just off the top of my head -- I believe I've run into the same issue before. When the iframe is first added to the dom, it has no src -- which makes Chrome "FAIL TO LOAD RESOURCE".

Try adding an initial src to the iframe --

 iframe = $("<iframe id='download' src='about:blank' style='display:none;'/>");

That should do it I believe. (you can downvote me a zillion times if it's wrong :))

ansiart
  • 2,563
  • 2
  • 23
  • 41
  • By the way, I tried looking at your jsfiddle link, and I received no error in the console, are you using 10.0.648.204? – ansiart Mar 30 '11 at 16:27
  • Thanks for the suggestion about including a `src`. I'm currently using 10.0.648.204 on OSX, but when I posted this question I most certainly was using something earlier. It looks like the test PDF file that I pointed to previously now results in a 200 OK, but the contents are empty. Should probably change the jsfiddle to point at a real PDF file to download and see how it works. – Tauren Apr 01 '11 at 05:20
  • are you still getting the error? I think the newer versions of chrome don't show an error on empty iframes anymore – ansiart Apr 01 '11 at 16:20
2

Chrome has a built-in PDF viewer. When you set the src of the iframe, Chrome just tries to display the PDF file. Since it's set to display:none, the download gets canceled and you get that message.

Try setting display to something other than none and position the iframe off the screen with position:absolute.

mattbasta
  • 13,492
  • 9
  • 47
  • 68
0
var downloadFile = function(url){
    var iframe = $("iframe#download");
    if (!iframe.length) {
        iframe = $("<iframe id='download' style='display:none;'/>");
        $("body").append(iframe);
    }
    iframe.attr("src", url);
    iframe.on('load',function(){
          console.log("error")
    });
};

U just try this,It is working, But this is not a correct way to solve this problem...

Vinoth
  • 11
  • 1
0

I changed the src of the file to one on my own web server and set the "content-type" of the response header to "application/octet-stream" instead of "application/pdf", and it downloaded correctly in Chrome. I should point out that the error still showed up in the console ("Error loading resource"), but it prompted me to download the file anyway.

Riley Dutton
  • 7,615
  • 2
  • 24
  • 26
-2

move your function outside of document.ready...

general functions should be always outside...and should be called whereever it is needed

$(document).ready( function() {    

    $("button").click(function() {    
        downloadFile("http://www.education.gov.yk.ca/pdf/pdf-test.pdf");
    });
});

    var downloadFile = function(url){
            var iframe = $("iframe#download");
            if (!iframe.length) {
                iframe = $("<iframe id='download' style='display:none;'/>");
                $("body").append(iframe);
            }
            iframe.attr("src", url);
        };
kobe
  • 15,671
  • 15
  • 64
  • 91
  • Thanks, and in my app I already do this. My example was just quick and dirty to illustrate the problem. But your answer doesn't address my question at all. Any ideas why I'm getting the `Failed to load resource` error message in Chrome? – Tauren Dec 04 '10 at 01:26
  • So when I click the button in JSFiddler it looks like all the elements of the page get smaller (I'm on Chrome 8.0.552.215). Aside from that, could you explain why removing the function from document.ready make this work? Edit: The page shrinkage is being caused by Chrome's zoom being set from 100% to 34% after clicking the button - weird. – Steven Dec 04 '10 at 01:27
  • You're right, @shambleh. That is very strange. I wonder what is causing that zoom change. Regardless, I'm still seeing the `Failed to load resource` error after moving the function out of `ready()`. Here's an updated version on jsfiddle: http://jsfiddle.net/94WvR/3/ I fail to see how the location of the function could possibly matter. – Tauren Dec 04 '10 at 04:00
  • The zoom happens when the PDF is rendered inline, as opposed to as an attachment. I had the same problem, but changed the way I render the PDF serverside, and it downloaded properly. I'm still getting the "Failed to load resource" error message though - not sure why that is. – funkymunky Jan 26 '11 at 21:35