Загрузка файла с помощью JAX-RS вместе с ajax и javascript blob-объектом не работает

Я пытаюсь загрузить файл, используя объект javascript Blob, но что-то странное происходит. Прежде всего, я использую 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 - это объект ByteArrayOutputStream, который я создаю из книги Apache POI. Если я использую обычный способ загрузки этого файла, то есть указывая браузер на ресурс JAX-RS, все работает нормально, но когда я пытаюсь использовать это решение qaru.site/info/23644/... он не работает, файл загружается поврежденным.

Когда я попытался отладить его в консоли Chrome, я обратил внимание на то, что разница между размером response и объектом Blob при попытке конвертировать ответ strong → 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 вопрос, который я упомянул выше:

$.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]*=((['"]).*?\2|[^;\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
        }
    }
});

Ответ 1

Ваши двоичные данные преобразуются в текст, это искажает ваши данные.
В настоящее время jQuery.Ajax не может выполнить типизированный запрос ajax, который вам нужен, поэтому вам нужно будет использовать простой XMLHttpRequest и установить responseType to blob, тогда XMLHttpRequest.response будут данные как blob