AngularJS:从服务器下载PDF文件

6
我想使用$http从Web服务器下载PDF文件。我使用了下面这段代码,它可以正常工作,但我的文件只能保存为HTML文件,当我打开它时,它在浏览器中以PDF格式打开。我在Chrome 36、Firefox 31和Opera 23上进行了测试。
这是我的AngularJS代码(基于此代码):
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);
                });

在我的服务器上,我使用Laravel框架,以下是我的响应:
$headers = array(
                'Content-Type' => $contentType,
                'Content-Length' => strlen($data),
                'Content-Disposition' => $contentDisposition
            );

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

其中$contentTypeapplication/pdf$contentDispositionattachment; filename=" . basename($fileName) . '"'

$filename - 例如59005-57123123.PDF

我的响应头:

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?


你能否在设置文件名后加上 console.log(filename) 并确认它是 invoice.pdf。还要确认在控制台中输入 document.createElement("a") 不会返回 undefined - Scott
文件名为159005-57123123.PDF,链接不是未定义的。 - Bartosz Bialecki
当您从代码中删除 $window.saveAs(blob, filename); return; 时会发生什么? - Scott
你能添加一个出现的“另存为”对话框的截图吗? - Scott
我会将其添加为答案。 :) - Scott
显示剩余7条评论
2个回答

1
为了指示浏览器下载文件而非在浏览器中显示它,请尝试向服务器响应添加以下标头:
Content-Disposition:attachment; filename="filename.xxx"
Content-Type:application/octet-stream

1
我已经正确设置了content-disposition。当我更改content-type时,没有任何变化。 - Bartosz Bialecki
1
@Jek-fdrv 要么使用简单的<a>标签,要么用JS打开它。 - user2899845

1

默认打开应用程序:

根据截图,看起来您已将Firefox设置为在该计算机上打开PDF文档的默认应用程序。它使用其嵌入式查看器打开。

因此,它保存为PDF,但是您的打开应用程序首选项使其显示为Firefox HTML文档。

如果您将打开应用程序首选项更改回Adobe Reader,则“另存为”类型应在浏览器中正确显示。

我希望这有所帮助。


1
@Jek-fdrv 这个问题无法通过前端代码解决。问题出在操作系统/浏览器软件的偏好设置上。这些设置需要由计算机用户/系统管理员进行配置。 - Scott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接