gpt4 book ai didi

jsf - 提供PDF下载后自动打开打印机对话框

转载 作者:行者123 更新时间:2023-12-04 10:38:42 25 4
gpt4 key购买 nike

我目前正在浏览器的新选项卡中打开 pdf 文件,但我需要知道如何在按下 commandButton 后打开打印机对话框以打印 pdf jasper 报告

这是在新标签页中打开pdf的方法:

public void printJasper() {

JasperReport compiledTemplate = null;
JRExporter exporter = null;
ByteArrayOutputStream out = null;
ByteArrayInputStream input = null;
BufferedOutputStream output = null;

FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

try {

List<String> sampleList = new ArrayList<String>();
sampleList.add("Fist sample string");
sampleList.add("Second sample string");

JRBeanCollectionDataSource beanCollectionDataSource = new JRBeanCollectionDataSource(sampleList);
Map<String, Object> reportValues = new HashMap<String, Object>();
reportValues.put("anyTestValue", "test value");

facesContext = FacesContext.getCurrentInstance();
externalContext = facesContext.getExternalContext();
response = (HttpServletResponse) externalContext.getResponse();

FileInputStream file = new FileInputStream("/any_dir/sample.jasper");
compiledTemplate = (JasperReport) JRLoader.loadObject(file);

out = new ByteArrayOutputStream();
JasperPrint jasperPrint = JasperFillManager.fillReport(compiledTemplate, reportValues, beanCollectionDataSource);

exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
exporter.exportReport();

input = new ByteArrayInputStream(out.toByteArray());

response.reset();
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(out.toByteArray().length));
response.setHeader("Content-Disposition", "inline; filename=\"fileName.pdf\"");
output = new BufferedOutputStream(response.getOutputStream(), Constants.DEFAULT_BUFFER_SIZE);

byte[] buffer = new byte[Constants.DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
output.flush();

} catch (Exception exception) {
/* ... */
} finally {
try {
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
} catch (Exception exception) {
/* ... */
}
}
facesContext.responseComplete();
}

这是打开pdf文件的按钮:
<p:commandButton action="#{sampleBB.printJasper}"
ajax="false" onclick="this.form.target='_blank'"
value="#{msg['generate.report']}" />

我需要做什么?

最佳答案

使用 JasperReports

使用 JasperReports 时,只需将此参数添加到 JasperReports 导出器:

exporter.setParameter(JRPdfExporterParameter.PDF_JAVASCRIPT, "this.print();");

这基本上指示 Adob​​e Acrobat 执行脚本 this.print()打开PDF时。另请参阅 Adobe Acrobat Scripting Guide 的第 79-80 页.以下是相关内容的摘录:

Printing PDF Documents

It is possible to use Acrobat JavaScript to specify whether a PDF document is sent to a printer or to a PostScript file. In either case, to print a PDF document, invoke the doc object’s print method. [...]



没有 JasperReports

如果您无法控制 PDF 的生成,因此无法操作它来添加提到的脚本,另一种方法是相应地更改所有 Java/JSF 代码,以便 PDF 文件幂等可用(即 PDF 文件必须仅通过 GET 请求而不是 POST 请求可用)。这允许您将其嵌入 <iframe>反过来,在加载期间可以通过 JavaScript 打印其内容(但请记住 CORS)。

简而言之,最终用户必须能够通过在浏览器的地址栏中输入其 URL 来下载所需的 PDF 文件。您当然可以使用 GET 请求查询字符串来指定参数,从而增加一点动态性。如果它是“非常大”的数据,那么您始终可以让 JSF 将其放入 HTTP session 或数据库中,然后将唯一标识符作为请求参数传递给周围,以便 servlet 可以从非常相同的 HTTP session 或数据库中获取它。

虽然可能有一些 nasty hacks ,JSF 支持 bean 根本不适合幂等地为非 JSF 响应提供服务的工作。你最好使用“普通 Vanilla ” servlet为了这。你最终会得到更简单的代码。这是此类 servlet 的启动示例:
@WebServlet("/pdf")
public class PdfServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String foo = request.getParameter("foo");
String bar = request.getParameter("bar");
// ...

// Now just use the same code as in your original bean *without* FacesContext.
// Note that the HttpServletResponse is readily available as method argument!
response.setContentType("application/pdf");
// ...
}

}

有了这个设置,它可以通过 http://localhost:8080/context/pdf?foo=abc&bar=xyz 获得。 .

一旦你让那部分工作,那么你只需要在 <iframe> 中引用它。它使用 JavaScript 在其 load 期间打印自己的内容窗口事件。您可以在 JSF 页面中执行此操作,例如 /pdf.xhtml :
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
<h:head>
<style>html, body { height: 100%; margin: 0; overflow: hidden; }</style>
</h:head>
<h:body>
<iframe src="#{request.contextPath}/pdf?#{request.queryString}"
width="100%" height="100%" onload="this.contentWindow.print()" />
</h:body>
</html>

您需要在 JSF 支持 bean 中执行的所有操作是发送重定向到该页面,如有必要,请使用请求查询字符串中的参数(它将以 #{request.queryString} 结尾,以便 servlet 可以通过 request.getParameter(...) 获取它们)。

这是一个启动示例:
<h:form target="_blank">
<h:commandButton value="Generate report" action="#{bean.printPdf}" />
</h:form>

public String printPdf() {
// Prepare params here if necessary.
String foo = "abc";
String bar = "xyz";
// ...

return "/pdf?faces-redirect=true"
+ "&foo=" + URLEncoder.encode(foo, "UTF-8")
+ "&bar=" + URLEncoder.encode(bar, "UTF-8");
}

关于jsf - 提供PDF下载后自动打开打印机对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23482263/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com