Oracle ADF 11g:如何将PDF文件发送至打印队列
Great question! Let's break down how to implement batch printing of your selected PDFs without opening each one individually. While a ValueChangeListener can track selections, a batch-triggered action (like a dedicated print button) will be more efficient and user-friendly. Here are two solid approaches:
Option 1: Backend Merge + Single Print (Recommended)
This approach combines all selected PDFs into a single document server-side, then serves it to the browser with a print trigger. It gives users a single print dialog, which is far smoother than multiple prompts.
Step 1: Update the Page Components
First, adjust your checkbox to bind to a selection map in your backing bean, and pass the PDF download URL as an attribute:
<af:panelGroupLayout id="pgl12" styleClass="itemAction" inlineStyle="padding:10px; vertical-align:bottom;"> <af:selectBooleanCheckbox id="dc_sbc1" value="#{viewScope.printingBean.selectedReports[attrs.item.id]}" label="Add"> <f:attribute name="downloadURL" value="#{attrs.item.downloadURL}"/> </af:selectBooleanCheckbox> <af:outputText id="print-label" styleClass="directoryButtonLabel" value="Add"/> </af:panelGroupLayout> <!-- Add a batch print button somewhere on your page --> <af:button text="Print Selected PDFs" actionListener="#{viewScope.printingBean.printSelectedReports}" onclick="setTimeout(function() { window.print(); }, 1500);"/>
Step 2: Backing Bean Implementation
Use a library like Apache PDFBox to merge the selected PDFs. Here's the bean code:
import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; import org.apache.pdfbox.multipdf.PDFMergerUtility; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletResponse; public class PrintingBean { private Map<String, Boolean> selectedReports = new HashMap<>(); public void printSelectedReports(ActionEvent event) { FacesContext facesContext = FacesContext.getCurrentInstance(); HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse(); try { PDFMergerUtility merger = new PDFMergerUtility(); ByteArrayOutputStream mergedStream = new ByteArrayOutputStream(); // Replace this with your actual method to fetch all report items List<ReportItem> allReports = getYourFullReportList(); for (ReportItem item : allReports) { Boolean isSelected = selectedReports.get(item.getId()); if (Boolean.TRUE.equals(isSelected)) { // Fetch the PDF from the download URL URL pdfUrl = new URL(item.getDownloadURL()); InputStream pdfStream = pdfUrl.openStream(); merger.addSource(pdfStream); } } // Merge all selected PDFs into one stream merger.setDestinationStream(mergedStream); merger.mergeDocuments(); // Configure response to display the merged PDF inline response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "inline; filename=selected_reports.pdf"); response.setContentLength(mergedStream.size()); // Write the merged PDF to the response mergedStream.writeTo(response.getOutputStream()); facesContext.responseComplete(); } catch (Exception e) { // Add a FacesMessage to notify users of errors e.printStackTrace(); } } // Getter/Setter for selectedReports public Map<String, Boolean> getSelectedReports() { return selectedReports; } public void setSelectedReports(Map<String, Boolean> selectedReports) { this.selectedReports = selectedReports; } // Replace with your actual method to retrieve all report items private List<ReportItem> getYourFullReportList() { // Your logic to fetch the list of reports being iterated in the JSF page return null; } }
Step 3: Add PDFBox Dependency
If using Maven, include this in your pom.xml:
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.32</version> <!-- Use the latest stable version --> </dependency>
Option 2: Frontend Print Trigger (No Merging)
If merging PDFs server-side isn't feasible, you can trigger print dialogs for each selected PDF via JavaScript. Note: This will prompt users for each PDF, which is less ideal but works for small batches.
Update the Page
Add a data attribute to your checkbox and a print button with a JS handler:
<af:selectBooleanCheckbox id="dc_sbc1" styleClass="print-selection" data-pdf-url="#{attrs.item.downloadURL}" value="#{viewScope.printingBean.selectedReports[attrs.item.id]}"> </af:selectBooleanCheckbox> <af:button text="Print Selected PDFs" onclick="printSelectedPDFs(); return false;"/>
Add JavaScript
function printSelectedPDFs() { const checkedBoxes = document.querySelectorAll('.print-selection:checked'); checkedBoxes.forEach(checkbox => { const pdfUrl = checkbox.getAttribute('data-pdf-url'); // Create a hidden iframe to load the PDF const iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = pdfUrl; iframe.onload = () => { // Trigger print after the PDF loads setTimeout(() => { iframe.contentWindow.print(); // Clean up the iframe after printing setTimeout(() => document.body.removeChild(iframe), 500); }, 1000); }; document.body.appendChild(iframe); }); }
Using ValueChangeListener (If You Prefer)
If you want to track selections as users check boxes, update your checkbox and bean like this:
<af:selectBooleanCheckbox id="dc_sbc1" autoSubmit="true" valueChangeListener="#{viewScope.printingBean.printerCheckboxListener}"> <f:attribute name="downloadURL" value="#{attrs.item.downloadURL}"/> </af:selectBooleanCheckbox>
Bean code:
import javax.faces.event.ValueChangeEvent; import java.util.ArrayList; import java.util.List; public class PrintingBean { private List<String> printQueue = new ArrayList<>(); public void printerCheckboxListener(ValueChangeEvent event) { Boolean isChecked = (Boolean) event.getNewValue(); String pdfUrl = (String) event.getComponent().getAttributes().get("downloadURL"); if (isChecked) { if (!printQueue.contains(pdfUrl)) { printQueue.add(pdfUrl); } } else { printQueue.remove(pdfUrl); } } // Add a print button action to process the printQueue (similar to Option 1/2 logic) }
内容的提问来源于stack exchange,提问作者dsalvado

