下载文件然后离开页面

时间:2017-03-08 16:00:04

标签: javascript asp.net-mvc

$http.post('@Url.Action("donePressed")',
{
    id: $scope.id,
}).then(
function (response) // success callback
{
    window.location = '@Url.Action("PdfCreator", "someController")?Id=' + $scope.id;
    window.location='@Url.Action("Index","AnotherController")';
},
function (response) // failure callback
{
    alert(response.statusText);
});

嗨,我想我做错了,我想打电话给一个函数,发送给我一个文件作为回复,之后我想离开页面去别的地方。 问题是,因为这是一个同步,我没有得到我的下载。

如何同步?

1 个答案:

答案 0 :(得分:0)

Async与它无关。一旦你进入成功回调,异步部分就已经完成了。问题是您在第一次更改有时间加载之前再次更改窗口位置。换句话说,它与异步问题完全相反;问题是这段代码是同步的,运行得太快。

然而,这里的方法有缺陷。如果浏览器被迫下载文件,可能工作,因为第一次更改window.location本身不会导致浏览器视图发生变化。由于PDF通常是浏览器可查看的类型,因此无法保证。无论如何,你仍然有同样的问题需要延迟第二次通话,直到第一次得到响应,这基本上是不可能的。对于这类事情没有内置事件,所以你能做的最好的事情就是使用setTimeout延迟1-2秒,并希望有足够的时间来获得第一个响应。即使这样,如果花费的时间更长,你的代码也会再次崩溃。换句话说,它会非常脆弱。

简单的事实是,这根本不是HTTP的工作方式。您基本上试图为单个请求返回两个响应,这是不可能的。这是试图绕过协议中固有限制的一种聪明方式,我会告诉你,但它最终还是不够。

所有这一切,你可以实际通过HTML5文件API和AJAX实现这一点,但你的解决方案只会兼容现代浏览器(基本上除IE 10及以下的所有内容)。如果您不需要支持较低版本的IE,则可以使用以下代码:

function (response) // success callback
{
    $http.get('@Url.Action("PdfCreator", "someController")?Id=' + $scope.id').then(
        function (response) // success callback
        {
            var a = document.createElement('a');
            var url = window.URL.createObjectURL(response.data);
            a.href = url;
            a.download = 'myfile.pdf';
            a.click();
            window.URL.revokeObjectURL(url);
            window.location = '@Url.Action("Index","AnotherController")';
        },
        function (response) // failure callback
        {
            alert(response.statusText);
        }
    );
},

秘诀在于通过AJAX获取PDF,然后从PDF数据中创建一个对象URL。然后,您可以使用它在DOM中创建一个锚元素,并动态“单击”它以提示下载。但需要注意的是,我没有尝试过使用Angular,所以我不确定$http是否支持获取二进制响应。我知道使用jQuery,你只需告诉它XHR对象的响应类型是'blob',但我不确定你是否可以或如何使用Angular做同样的事情。作为替代方案,您只需将XMLHttpRequest直接用于此特定AJAX,只需设置xhr.responseType = 'blob'