RS together with ajax and javascript's blob object, doesn't work
I trying to download file by using javascript's Blob object, but something weird is happening. First of all I use JAX-RS to send the file from backend, this is my code:
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
is 'ByteArrayOutputStream' object which I create from Apache POI workbook. If I use regular way to download this file, ie pointing browser to JAX-RS resource, everything works fine, but when I try to use this solution https://stackoverflow.com/a/23797348/947111 it doesn't work, file being downloaded corrupted.
When I tried to debug it in Chrome's console I paid attention that there's difference in size between response object and Blob object when I trying convert response to Blob . Size of the response is 4096 bytes,
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
But when I perform var blob = new Blob([response], { type: type });
, blob becomes the size of 7836 bytes, ie when I perform blob.size
in console, I get this size. Downloaded file's size is 7834 bytes. But when I stop debugger at this point var downloadUrl = URL.createObjectURL(blob);
and point browser in another tab to downloadURL
, downloaded file's size appear to be 7836 bytes, and appears to be corrupted too. So, my question is why it doesn't work and why there's difference in size? I use Chrome Version 40.0.2214.111 (64-bit) , but in Firefox 35.0.1 I have a same behaviour.
Thank you in advance.
PS The full code of my client side from SO question which I mentioned above:
$.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
}
}
});
Your binary data is converted to text, this corrupts your data.
Currently jQuery.Ajax cannot do a typed ajax request, which is what you need, therefore you'll have to use bare XMLHttpRequest and set the responseType
to blob
then XMLHttpRequest.response
will be the data as a blob
上一篇: jquery ajax调用问题