使用 JAX-RS 与 ajax 和 javascript 的 blob 对象一起下载文件不起作用

Downloading file by using JAX-RS together with ajax and javascript's blob object, doesn't work

我尝试使用 javascript's Blob object 下载文件,但发生了一些奇怪的事情。 首先,我使用 JAX-RS 从后端发送文件,这是我的代码:

    Workbook wb = new HSSFWorkbook();

    //creating workbook...

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try {
        wb.write(bos);
        bos.close();
    } catch(Exception e) {
        e.printStackTrace();
    }
    byte[] bytes = bos.toByteArray();
    return Response.ok(bytes).header("Content-Disposition", "attachment; filename=" + "test.xls").build();

bos 是我从 Apache POI 工作簿创建的 'ByteArrayOutputStream' 对象。如果我使用常规方式下载此文件,即将浏览器指向 JAX-RS 资源,一切正常,但当我尝试使用此解决方案时 它不会工作,正在下载的文件已损坏。

当我尝试在 Chrome 的控制台中调试它时,我注意到 response 对象和 Blob[= 之间存在大小差异46=] 对象,当我尝试将 response 转换为 Blob 时。 响应的大小 是 4096 字节,

Date: Tue, 10 Feb 2015 17:32:27 GMT
Server: WildFly/8
Connection: keep-alive
X-Powered-By: Undertow/1
Content-Length: 4096
Content-Disposition: attachment; filename=test.xls
Content-Type: application/vnd.ms-excel

但是当我执行var blob = new Blob([response], { type: type });时,blob变成了7836字节的大小,即当我在控制台执行blob.size时,我得到这个大小。下载文件的大小为 7834 字节。但是,当我在此时 var downloadUrl = URL.createObjectURL(blob); 停止调试器并将另一个选项卡中的浏览器指向 downloadURL 时,下载文件的大小似乎是 7836 字节,而且似乎也已损坏。 所以,我的问题是为什么它不起作用以及为什么大小不同? 我使用 Chrome 版本 40.0.2214.111(64 位),但在 Firefox 35.0.1 中我有相同的行为。

提前谢谢你。

P.S。我在上面提到的 SO question 客户端的完整代码:

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

        var type = xhr.getResponseHeader('Content-Type');
        var blob = new Blob([response], { type: type });

        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 = downloadUrl;
                } else {
                    a.href = downloadUrl;
                    a.download = filename;
                    document.body.appendChild(a);
                    a.click();
                }
            } else {
                window.location = downloadUrl;
            }

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

您的二进制数据已转换为文本,这会损坏您的数据。
当前 jQuery.Ajax 无法执行类型化的 ajax 请求,而这正是您所需要的,因此您必须使用裸 XMLHttpRequest 并将 responseType to blob then XMLHttpRequest.response 数据设置为 blob