6

I want to download a pdf file from the web server using $http. I use this code which works great, my file only is save as a html file, but when I open it it is opened as pdf but in the browser. I tested it on Chrome 36, Firefox 31 and Opera 23.

This is my angularjs code (based on this code):

UserService.downloadInvoice(hash).success(function (data, status, headers) {
                    var filename,
                        octetStreamMime = "application/octet-stream",
                        contentType;

                    // Get the headers
                    headers = headers();

                    if (!filename) {
                        filename = headers["x-filename"] || 'invoice.pdf';
                    }

                    // Determine the content type from the header or default to "application/octet-stream"
                    contentType = headers["content-type"] || octetStreamMime;

                    if (navigator.msSaveBlob) {
                        var blob = new Blob([data], { type: contentType });
                        navigator.msSaveBlob(blob, filename);
                    } else {
                        var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;

                        if (urlCreator) {
                            // Try to use a download link
                            var link = document.createElement("a");

                            if ("download" in link) {
                                // Prepare a blob URL
                                var blob = new Blob([data], { type: contentType });
                                var url = urlCreator.createObjectURL(blob);

                                link.setAttribute("href", url);
                                link.setAttribute("download", filename);

                                // Simulate clicking the download link
                                var event = document.createEvent('MouseEvents');
                                event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
                                link.dispatchEvent(event);
                            } else {
                                // Prepare a blob URL
                                // Use application/octet-stream when using window.location to force download
                                var blob = new Blob([data], { type: octetStreamMime });
                                var url = urlCreator.createObjectURL(blob);
                                $window.location = url;
                            }
                        }
                    }
                }).error(function (response) {
                    $log.debug(response);
                });

On my server I use Laravel and this is my response:

$headers = array(
                'Content-Type' => $contentType,
                'Content-Length' => strlen($data),
                'Content-Disposition' => $contentDisposition
            );

            return Response::make($data, 200, $headers);

where $contentType is application/pdf and $contentDisposition is attachment; filename=" . basename($fileName) . '"'

$filename - e.g. 59005-57123123.PDF

My response headers:

Cache-Control:no-cache
Connection:Keep-Alive
Content-Disposition:attachment; filename="159005-57123123.PDF"
Content-Length:249403
Content-Type:application/pdf
Date:Mon, 25 Aug 2014 15:56:43 GMT
Keep-Alive:timeout=3, max=1

enter image description here

What am I doing wrong?

Community
  • 1
  • 1
Bartosz Bialecki
  • 4,391
  • 10
  • 42
  • 64
  • Can you put a `console.log(filename)` after where filename is set and confirm it is `invoice.pdf`. And also confirm that typing `document.createElement("a")` into the console does not return `undefined` – Scott Aug 25 '14 at 16:13
  • filename is 159005-57123123.PDF and link is not undefined. – Bartosz Bialecki Aug 26 '14 at 07:53
  • What happens when you remove the `$window.saveAs(blob, filename); return;` that you have added to the code. – Scott Aug 26 '14 at 08:32
  • Oh sorry, this is my mistake, I forget to remove it when I trying other solutions, but the problem remains. – Bartosz Bialecki Aug 26 '14 at 08:46
  • Can you add a screenshot of the save-as dialog that appears? – Scott Aug 26 '14 at 09:02
  • Maybe I am doing something wrong on the server side? – Bartosz Bialecki Aug 26 '14 at 09:09
  • That looks like you have set FireFox as the default application to open your PDF documents on that computer. So it is saving as a PDF, but your open-in application preferences make it appear as `Firefox html document`. – Scott Aug 26 '14 at 09:15
  • Yes you're right, I am idiot, sorry. I can now open it with acrobat reader, while saving it is still shown as html document, but I think i need to clear browser data then maybe should work. Thank you. – Bartosz Bialecki Aug 26 '14 at 09:28
  • I'll add that as the answer. :) – Scott Aug 26 '14 at 09:45
  • Of course, you should do it :) – Bartosz Bialecki Aug 26 '14 at 09:49
  • I implemented this download code as well, but my file is downloaded partly only. My question is at http://stackoverflow.com/questions/26767160/download-a-zip-file-in-angularjs – Stephane Nov 06 '14 at 10:19

2 Answers2

1

To instruct the browser to download the file instead of showing it in the browser, try the add following headers to the server response:

Content-Disposition:attachment; filename="filename.xxx"
Content-Type:application/octet-stream
user2899845
  • 1,181
  • 9
  • 13
1

Default Open-In Application:

Based on the screenshot, it looks like you have set Firefox as the default application to open your PDF documents on that computer. Which it does, using it's embedded viewer.

So it is saving as a PDF, but your open-in application preferences make it appear as Firefox Html Document.

If you change the open-in preference back to Adobe Reader then the Save-As type should display correctly in the browser.

I hope that helps.

Community
  • 1
  • 1
Scott
  • 21,211
  • 8
  • 65
  • 72
  • 1
    @Jek-fdrv this issue cannot be solved by code in the front end. The problem is with the operating system/browsing software preferences. They will have to be set by the computer user/system administrator. – Scott Mar 30 '16 at 17:43