iOS设备上的JSF Streaming PDF

时间:2011-09-28 15:27:35

标签: ios jsf

我有一个JSF页面,它使用支持bean将PDF文档流式传输到浏览器。这个功能很好用,直到现在我在iOS设备上测试这个功能时还没有遇到任何问题。

在iPad和iPod Touch上的Safari上,PDF流最终只是在获得响应时被粘贴为网页上的不可滚动图层。在桌面上的浏览器中,该文件提示使用Adobe Reader正确保存或打开并打开。这是一个问题,因为只有PDF的第一页的一部分显示在iOS设备上,并且无法查看其他部分。

我已经在网络上对这些设备上的其他PDF进行了测试,但它们的行为并不相同。启动PDF应用程序或Safari加载可滚动预览,这是预期的结果。还有其他人有这个吗?

我的支持bean正在将PDF的缓冲输入流写入输出流。我已设置以下响应标头:

response.setContentType ("application/pdf"); 
response.setContentLength(inputLength); 
response.setHeader ("Content-Disposition", "inline;filename=\"" + saveFilename + ".pdf\""); 
response.setHeader ("Cache-Control", "must-revalidate, post-check=0, pre-check=0, public"); 

我试图将内容处置从内联切换到附件,但这没有帮助。

1 个答案:

答案 0 :(得分:0)

我认为这些设备在服务器端需要Range支持,以便可以在单独的部分中请求内容。这最终可以最终节省不必要的网络带宽,并改善客户端的性能感受。

如果这些PDF是动态生成的,那么最好的办法是将它们写入磁盘文件系统中的临时位置,并将请求重定向到由servlet读取的URL。拥有物理文件是必需的,因为您希望使用RandomAccessFile以便能够返回文件的部分内容。此类需要磁盘上的物理File

这是一个使用File#createTempFile()创建临时文件并使用文件名作为URL参数将响应重定向到servlet的示例:

File tempFile = File.createTempFile(saveFilename, ".pdf");
OutputStream output = new FileOutputStream(tempFile);
// Now write PDF to output.
// ...

// Then, redirect to some servlet URL.
String tempFilename = tempFile.getName();
externalContext.redirect("/pdf/" + URLEncoder.encode(tempFilename, "UTF-8"));

然后,您需要一个支持范围请求的this one之类的servlet。您只需修改它即可将basePath值更改为System.getProperty("java.io.tmpdir")。最后将此servlet映射到/pdf/*

的URL模式

或者,如果您对服务器拥有完全的管理控制权,那么您还可以创建一个额外的webapp上下文,指向服务器磁盘文件系统某处的绝对路径。例如。 /var/webapp/pdf。对于例如Tomcat,您可以通过将以下内容添加到/conf/server.xml

来公开此功能
<Context docBase="/var/webapp/pdf" path="/pdf" />

这样/var/webapp/pdf文件夹的内容由http://localhost:8080/context/pdf提供。

在上面的代码示例中稍作更改以指定临时文件位置

File tempFile = File.createTempFile(saveFilename, ".pdf", "/var/webapp/pdf");
// ...

您不再需要自定义servlet了。 Tomcat的DefaultServlet将负责正确处理Range个请求。

最后但同样重要的是,考虑将临时文件存储在会话中并实现HttpSessionListenerHttpSessionAttributeListener,以便在会话过期时删除临时文件。