【发布时间】:2012-03-28 20:52:34
【问题描述】:
我目前在 Android 设备上的网页中遇到了一个奇怪的问题。
我想要做的是允许用户将 pdf 文件下载到他的移动设备上。因此,我在here 描述的设置中提供了一个下载按钮。
只要我使用我的桌面浏览器 *Mozilla Firefox 10.** 一切正常,但只要我更改为我的移动设备(SGS II,Android 版本 2.3.5)下载结果取决于我使用的浏览器应用程序。
Mozilla 和 Opera 移动版:
两者似乎都能正确下载文件。
任何其他浏览器应用程序(内置、Dolphin HD、...):
下载一个名为 <filename>.pdf 或 <filename>.htm 的文件,它们都代表一个 .htm 文件,显示页面的 html 源代码。
我的尝试:
-
使用了 PrimeFaces 库中的
StreamedContent方法public StreamedContent getFile() { // prepare file for download // reference webDAV directory and get file as stream this.file = new Helper().getWebDavFile(customerId, fileName); return file; } -
如here 所述,手动将文件流式传输到页面。 (感谢 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(); } -
将
<a href="">设置为文件的本地副本。
(我目前使用的是<p:commandButton>,所以我必须使用执行重定向而不是返回字符串的方法,但它可以双向工作)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); }即使在我的 android 设备上,最后的方法也能正常工作,但如果我可以避免它,我不想走这条路,因为文件是从 WebDAV 流式传输的,我必须保存每个文件到服务器。这会产生更多的 IO 负载并迫使我手动清理。
Helper().getWebDavFile 和 Helper().getWebDavFileManually 方法要么返回 PrimeFaces 使用的 DefaultStreamedConten,要么返回 byte[] 用于我自己的方法。
到目前为止我所知道的:
不幸的是,这不是我的问题的解决方案 :)。
在使用 google 几个小时后,我发现可能存在 double-http-post-request。这将导致 androids 内部下载管理器(用于文件下载损坏的情况)发送一个额外的后请求,其中状态丢失。
正如this blog 中所述(参见GET、POST、REST [UPDATE 20120208] 部分),有人面临同样的问题。我已经尝试了此博客中提到的所有方法,但没有成功。
在这个forum 上,有人用 WireShark 分析了相同的行为并得出了几乎相同的结论。
我没有找到更多的资源,所以我被困在了这里。
我还在 PrimeFaces forum 上发帖,只是为了确保没有任何关于 <p:fileDownload> 组件的已知问题。
我想知道的:
我错过了什么吗?
是否有可能从 Android 设备上的 JSF(http-post 操作)网页下载流文件?
任何帮助/建议/信息将不胜感激!
提前致谢!
【问题讨论】:
-
这是一个讨厌的问题。 POST 真的是强制性的吗?看起来这正是罪魁祸首。您还可以对 JSF 托管 bean 执行 GET 操作,尽管我宁愿为此使用一个简单的 servlet。
标签: jakarta-ee jsf-2 download http-post android