I'm currently facing a weird problem in my webpage on android devices.
What I want to do is to allow a user to download a pdf-file to his mobile device. Therefore I provide a download button as in the setup described here.
Everything works fine as long as I use my desktop browser *Mozilla Firefox 10.** but as soon as I change to my mobile device (SGS II, Android vers. 2.3.5) the result of the download depends on the browser-app I'm using.
Mozilla and Opera mobile:
Both seem to be able to download the file correctly.
Any other browser-app (built-in, Dolphin HD,...):
Downloads a file either named <filename>.pdf
or <filename>.htm
which both represent a .htm-file showing the html-source of the page.
What I've tried:
Used the
StreamedContent
method out of the PrimeFaces librarypublic StreamedContent getFile() { // prepare file for download // reference webDAV directory and get file as stream this.file = new Helper().getWebDavFile(customerId, fileName); return file; }
Streamed the file manually to the page as described here. (Thx to BalusC)
public void download() throws IOException { byte[] is = new Helper().getWebDavFileManually(customerId, fileName); FacesContext fc = FacesContext.getCurrentInstance(); ExternalContext ec = fc.getExternalContext(); ec.responseReset(); ec.setResponseContentType("application/pdf"); ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + fileName.toUpperCase() + "\""); OutputStream output = ec.getResponseOutputStream(); output.write(is); fc.responseComplete(); }
Set an
<a href="">
to a local copy of the file.
(I'm currently using a<p:commandButton>
so I've to use a method executing a redirect instead of returning a String but it works in both ways)public void goToLink() throws IOException { // get WebDAV file and save temporarily byte[] b = new Helper().getWebDavFileManually(customerId, fileName); String path = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/") + fileName; File f = new File(path); try { FileOutputStream fos = new FileOutputStream(f); fos.write(b); link = "http://someurl/somepage/" + fileName; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // use link ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext(); ec.redirect(link); }
This final approach worked fine even on my android device but I do not want to go this route if I can avoid it because the file gets streamed from a WebDAV an I'd have to save each file to the server. This would produce more IO load and would force me to manually clean-up.
The methods Helper().getWebDavFile
and Helper().getWebDavFileManually
either return a DefaultStreamedConten used by PrimeFaces or a byte[] for my own approach.
What I know so far:
Unfortunately not the solution for my problem :).
After many hours of using google I found out that there is the possibility of a double-http-post-request. This would cause androids internal download manager (used in case of broken file download) to send an additional post-request in which the state gets lost.
As described in this blog (see section GET, POST, REST [UPDATE 20120208]) there is someone facing the same problem. I've tried all approaches mentioned on this blog but didn't succeed.
On this forum someone analyzed the same behavior with WireShark and got nearly to the same conclusion.
I didn't found any more ressources so I'm stuck at this.
I've also posted on the PrimeFaces forum just to make sure that there aren't any known issues regarding the <p:fileDownload>
component.
What I would like to know:
Am I missing something?
Is there any possibility to download a streamed file from an JSF (http-post operating) webpage on an android device?
Any help/suggestion/information would be appreciated!
Thanks in advance!