javascript - 处理从ajax post下载的文件

标签 javascript jquery ajax

我有一个 JavaScript 应用程序,它将 ajax POST 请求发送到某个 URL。响应可能是 JSON 字符串,也可能是文件(作为附件)。我可以轻松地在 ajax 调用中检测 Content-Type 和 Content-Disposition,但是一旦我检测到响应包含文件,我如何向客户端提供下载它?我在这里阅读了许多类似的帖子,但没有一个提供我正在寻找的答案。

请,请,请不要发布建议我不应该使用 ajax 或我应该重定向浏览器的答案,因为这些都不是一个选项。使用纯 HTML 表单也不是一种选择。我真正需要的是向客户端显示一个下载对话框。这可以做到吗?如何做到?

最佳答案

不要这么快放弃,因为这可以使用部分 FileAPI 来完成(在现代浏览器中):

var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.responseType = 'blob';
xhr.onload = function () {
    if (this.status === 200) {
        var blob = this.response;
        var filename = "";
        var disposition = xhr.getResponseHeader('Content-Disposition');
        if (disposition && disposition.indexOf('attachment') !== -1) {
            var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
            var matches = filenameRegex.exec(disposition);
            if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
        }

        if (typeof window.navigator.msSaveBlob !== 'undefined') {
            // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
            window.navigator.msSaveBlob(blob, filename);
        } else {
            var URL = window.URL || window.webkitURL;
            var downloadUrl = URL.createObjectURL(blob);

            if (filename) {
                // use HTML5 a[download] attribute to specify filename
                var a = document.createElement("a");
                // safari doesn't support this yet
                if (typeof a.download === 'undefined') {
                    window.location.href = downloadUrl;
                } else {
                    a.href = downloadUrl;
                    a.download = filename;
                    document.body.appendChild(a);
                    a.click();
                }
            } else {
                window.location.href = downloadUrl;
            }

            setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
        }
    }
};
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send($.param(params, true));

或者如果使用 jQuery.ajax:

$.ajax({
    type: "POST",
    url: url,
    data: params,
    xhrFields: {
        responseType: 'blob' // to avoid binary data being mangled on charset conversion
    },
    success: function(blob, status, xhr) {
        // check for a filename
        var filename = "";
        var disposition = xhr.getResponseHeader('Content-Disposition');
        if (disposition && disposition.indexOf('attachment') !== -1) {
            var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
            var matches = filenameRegex.exec(disposition);
            if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
        }

        if (typeof window.navigator.msSaveBlob !== 'undefined') {
            // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
            window.navigator.msSaveBlob(blob, filename);
        } else {
            var URL = window.URL || window.webkitURL;
            var downloadUrl = URL.createObjectURL(blob);

            if (filename) {
                // use HTML5 a[download] attribute to specify filename
                var a = document.createElement("a");
                // safari doesn't support this yet
                if (typeof a.download === 'undefined') {
                    window.location.href = downloadUrl;
                } else {
                    a.href = downloadUrl;
                    a.download = filename;
                    document.body.appendChild(a);
                    a.click();
                }
            } else {
                window.location.href = downloadUrl;
            }

            setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
        }
    }
});

关于javascript - 处理从ajax post下载的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56776171/

相关文章:

javascript - 如何阻止谷歌地图地理编码在N秒后返回

javascript - 字母数字的正则表达式,没有空格和 9 个字符输入?

javascript - 尝试检查字符串是否为空,但检查不正常

javascript - ajax、setRequestHeader()、Content-Type、application/x-www-form-urlencoded 和 charset

javascript - 使用 jquery 获取的 url 参数扩展 Accordion 菜单并将 attr 添加到所需的类

react-flux 中的 Javascript 获取 API

ajax - 有没有比在 SharePoint WebParts 中使用 Ajax 更新面板更好的方法?

php - 使用PHP+Ajax+jQuery可编辑数据库表

javascript - 确定属性是否是 Chrome/Firefox 中的 native DOM 属性

javascript - 使用油脂猴脚本实现轮询