I have this problem. In synthesis, i have a download button that, when clicked, performs an Ajax request like this:
Ext.Ajax.request({
url: 'DownloadServlet',
method: 'GET',
});
This request is processed by a servlet that reads default file. The reading of the file is successful, in fact, in firebug, the state of the GET is "200".
The problem is that the front-end (extjs) does not appear to manage to download the file. I would expect the browser showed the classic more window to download the file.
What could it be? thanks
I have this problem. In synthesis, i have a download button that, when clicked, performs an Ajax request like this:
Ext.Ajax.request({
url: 'DownloadServlet',
method: 'GET',
});
This request is processed by a servlet that reads default file. The reading of the file is successful, in fact, in firebug, the state of the GET is "200".
The problem is that the front-end (extjs) does not appear to manage to download the file. I would expect the browser showed the classic more window to download the file.
What could it be? thanks
Share Improve this question edited Jun 26, 2013 at 7:40 Brian 5,0288 gold badges41 silver badges58 bronze badges asked Oct 24, 2012 at 13:30 Francesco NigroFrancesco Nigro 4882 gold badges8 silver badges21 bronze badges2 Answers
Reset to default 3Try this
downloadWhatever : function() {
Ext.core.DomHelper.append(document.body, {
tag : 'iframe',
id : 'downloadIframe',
frameBorder : 0,
width : 0,
height : 0,
css : 'display:none;visibility:hidden;height:0px;',
src : '/your/restful/url/'
});
},
Server side spring (in case you were wondering)
@RequestMapping(value = "/url", method = RequestMethod.GET)
public void download(HttpServletRequest request,
HttpServletResponse response) throws ServletRequestBindingException, IOException {
String tempFile = .. get your file
File file = new File(tempFile);
// in case you have zipped it ...
// else set the correct ContentType
response.setContentType("application/zip");
response.setContentLength((int) file.length());
response.setHeader("fileName", file.getName());
response.setHeader("Content-Disposition", "attachment; filename="+ file.getName());
InputStream in = new FileInputStream(file);
OutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int read = 0;
while ((read = in.read(buffer, 0, buffer.length)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.flush();
out.close();
}
You can't download file with AJAX call. Basicly there is 2 solutions: hard and simple.
Simple: just use window.popup or document.location.href to redirect on url where your file is stored and you'll get normal browser methods of downloading. Just be sure you are sending mimetype which browser will not render, like application/octet-stream
Hard: you can get binary or base64 encoded file content with AJAX call and create a download link with base64 encoded href. In Chrome it will look like that:
<a href="base64,mime-type,...encoded trash..." download="download">
There is some solutions for other browsers, but currently it works ideally only in Chrome. For other browsers I'm using code like that:
var showSave;
// Feature test: Does this browser support the download attribute on anchor tags? (currently only Chrome)
var DownloadAttributeSupport = 'download' in document.createElement('a');
// Use any available BlobBuilder/URL implementation:
var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
// IE 10 has a handy navigator.msSaveBlob method. Maybe other browsers will emulate that interface?
// See: http://msdn.microsoft./en-us/library/windows/apps/hh441122.aspx
navigator.saveBlob = navigator.saveBlob || navigator.msSaveBlob || navigator.mozSaveBlob || navigator.webkitSaveBlob;
// Anyway, HMTL5 defines a very similar but more powerful window.saveAs function:
// http://www.w3/TR/file-writer-api/#the-filesaver-interface
window.saveAs = window.saveAs || window.webkitSaveAs || window.mozSaveAs || window.msSaveAs;
// However, this is not supported by any browser yet. But there is a patibility library that
// adds this function to browsers that support Blobs (except Internet Exlorer):
// http://eligrey./blog/post/saving-generated-files-on-the-client-side
// https://github./eligrey/FileSaver.js
// mime types that (potentially) don't trigger a download when opened in a browser:
var BrowserSupportedMimeTypes = {
"image/jpeg": true,
"image/png": true,
"image/gif": true,
"image/svg+xml": true,
"image/bmp": true,
"image/x-windows-bmp": true,
"image/webp": true,
"audio/wav": true,
"audio/mpeg": true,
"audio/webm": true,
"audio/ogg": true,
"video/mpeg": true,
"video/webm": true,
"video/ogg": true,
"text/plain": true,
"text/html": true,
"text/xml": true,
"application/xhtml+xml": true,
"application/json": true
};
// Blobs and saveAs (or saveBlob) :
if (BlobBuilder && (window.saveAs || navigator.saveBlob)) {
// Currently only IE 10 supports this, but I hope other browsers will also implement the saveAs/saveBlob method eventually.
showSave = function (data, name, mimeType) {
var builder = new BlobBuilder();
builder.append(data);
var blob = builder.getBlob(mimetype||"application/octet-stream");
if (!name) name = "Download.bin";
// I don't assign saveAs to navigator.saveBlob (or the other way around)
// because I cannot know at this point whether future implementations
// require these methods to be called with 'this' assigned to window (or
// naviagator) in order to work. E.g. console.log won't work when not called
// with this === console.
if (window.saveAs) {
window.saveAs(blob, name);
}
else {
navigator.saveBlob(blob, name);
}
};
}
else if (window.Blob && URL && window.atob) {
// atob to base64_decode the data-URI
showSave = function (data, name, mimetype) {
var image_data = atob(data);
// Use typed arrays to convert the binary data to a Blob
var arraybuffer = new ArrayBuffer(image_data.length);
var view = new Uint8Array(arraybuffer);
for (var i=0; i<image_data.length; i++) {
view[i] = image_data.charCodeAt(i) & 0xff;
}
var blob = new Blob([arraybuffer], {type: 'application/octet-stream'});
// Use the URL object to create a temporary URL
var url = URL.createObjectURL(blob);
//window.open(url, '_blank', '');
document.location.href = url
}
}
// Blobs and object URLs:
else if (BlobBuilder && URL) {
// Currently WebKit and Gecko support BlobBuilder and object URLs.
showSave = function (data, name, mimetype) {
var blob, url, builder = new BlobBuilder();
builder.append(data);
if (!mimetype) mimetype = "application/octet-stream";
if (DownloadAttributeSupport) {
blob = builder.getBlob(mimetype);
url = URL.createObjectURL(blob);
// Currently only Chrome (since 14-dot-something) supports the download attribute for anchor elements.
var link = document.createElement("a");
link.setAttribute("href",url);
link.setAttribute("download",name||"Download.bin");
// Now I need to simulate a click on the link.
// IE 10 has the better msSaveBlob method and older IE versions do not support the BlobBuilder interface
// and object URLs, so we don't need the MS way to build an event object here.
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
}
else {
// In other browsers I open a new window with the object URL.
// In order to trigger a download I have to use the generic binary data mime type
// "application/octet-stream" for mime types that browsers would display otherwise.
// Of course the browser won't show a nice file name here.
if (BrowserSupportedMimeTypes[mimetype.split(";")[0]] === true) {
mimetype = "application/octet-stream";
}
blob = builder.getBlob(mimetype);
url = URL.createObjectURL(blob);
//window.open(url, '_blank', '');
document.location.href = url
}
// The timeout is probably not necessary, but just in case that some browser handle the click/window.open
// asynchronously I don't revoke the object URL immediately.
setTimeout(function () {
URL.revokeObjectURL(url);
}, 250);
// Using the filesystem API (http://www.w3/TR/file-system-api/) you could do something very similar.
// However, I think this is only supported by Chrome right now and it is much more plicated than this
// solution. And chrome supports the download attribute anyway.
};
}
// data:-URLs:
else if (!/\bMSIE\b/.test(navigator.userAgent)) {
// IE does not support URLs longer than 2048 characters (actually bytes), so it is useless for data:-URLs.
// Also it seems not to support window.open in bination with data:-URLs at all.
showSave = function (data, name, mimetype) {
if (!mimetype) mimetype = "application/octet-stream";
// Again I need to filter the mime type so a download is forced.
if (BrowserSupportedMimeTypes[mimetype.split(";")[0]] === true) {
mimetype = "application/octet-stream";
}
// Note that encodeURIComponent produces UTF-8 encoded text. The mime type should contain
// the charset=UTF-8 parameter. In case you don't want the data to be encoded as UTF-8
// you could use escape(data) instead.
window.open("data:"+mimetype+";base64,"+data, '_blank', '');
};
}
// Internet Explorer before version 10 does not support any of the methods above.
// If it is text data you could show it in an textarea and tell the user to copy it into a text file.
Updated: If you are ok to use Flash, here is fallback solution for non-Chrome browsers: https://github./dcneiner/Downloadify