Automatically Print Web-based Oracle Reports (PDF format) to a User's Local/Default Printer
Working for a major metropolitan police department, I get some interesting development assignments. One such assignment was to allow officers connected to our network via VPN to send their printed reports to the default printer assigned to the machine they are using. No problem! Oracle Reports has a setting that will send a PDF version of the report back to the user's web browser using the Adobe Acrobat plug-in. They can just hit the print button in the Acrobat viewer and print the report to any printer available to the machine! No sweat! Oh ... by the way ... the officer is not allowed to save the report to his/her machine (for security and privacy reasons). This is where the task got sticky. The Acrobat Viewer has a 'Save' button. This feature cannot be turned off programmatically. A command has to be impeded in PDF document at the time it is created to keep it from being saved. Unfortunately, Oracle Reports doesn't offer this as an option for reports being created in a PDF format (at least in our version). After a little searching, I found a solution. The rest of this entry will show you how to do it using an open source tool and some standard browser features. Nothing is impossible ...
The Solution ...
The solution to the problem was to imbed a JavaScript command in the PDF document that forced an auto print to the default printer while accessing the document from a hidden IFRAME (width 0, height 0). The only hitch … how the heck do we imbed a JavaScript command in a PDF document that is being generated by Oracle Reports. This is where the open source option came into play. After some searching, I came across an open source project called iText (http://www.lowagie.com/iText/). iText is a library that allows you to generate or modify (to some extent) PDF files on the fly. iText is available in both Java and .NET flavors. Being a Java fan and an Oracle Application Server customer, I chose the Java flavored iText solution. I created a servlet that acted as a proxy to the Oracle Reports Servlet. The servlet, acting as a proxy, is then able to received the data stream from the Oracle Reports servlet. In this case, the data stream is a PDF document. Using the iText library, I added the auto print command to the PDF document and then had the proxy servlet pass the altered document to the user's browser. To keep the user from saving this document, I had the request for the report sent to the proxy servlet through an IFRAME with a width and height of 0. This kept the user from seeing the document in the Adobe Acrobat plug-in and kept them from saving the document.
The Code ...
Being a left-handed right-brained developer, I tend to learn more from actually seeing the code than reading about it. The iText APIs are well documented at the iText website (http://www.lowagie.com/iText) along with examples. JavaScript commands as they relate to PDF documents can be found at http://partners.adobe.com/public/developer/pdf/library/index.html. I have included comments in the code in key locations. As usual, if you have questions, shoot me an email. Here is the code for the servlet:
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.PdfWriter;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import javax.servlet.*;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URL;
import java.net.MalformedURLException;
//iText Open Source PDF APIs ... awesome code!
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
public class PDFLocalPrint extends HttpServlet
{
private static final String CONTENT_TYPE = "application/pdf";
public void init(ServletConfig config) throws ServletException
{
super.init(config);
}
private ByteArrayOutputStream getDoc(String p_url)
{
Document document = null;
PdfCopy writer = null;
PdfImportedPage page;
ByteArrayOutputStream baos = null;
int v_pages = 0;
try{
URL url = new URL(p_url);
URLConnection urlc= url.openConnection();
int length = urlc.getContentLength();
InputStream in = urlc.getInputStream();
baos = new ByteArrayOutputStream();
PdfReader oracleReport = new PdfReader(in);
oracleReport.consolidateNamedDestinations();
v_pages = oracleReport.getNumberOfPages();
document = new Document(oracleReport.getPageSizeWithRotation(1));
writer = new PdfCopy(document,baos);
document.open();
//Copy content from PDF streaming from Reports Server to new PDF Document.
for(int i=0;i<v_pages;)
{ i++;
page = writer.getImportedPage(oracleReport,i);
writer.addPage(page);
}
//Append Javascript command Add Silent Print command
//"this.print({bUI:false,bSilent:true,bShrinkToFit:true});"
writer.addJavaScript(Constants.SILENT_PRINT, false);
document.close();
}catch(Exception e)
{
System.out.println("Error - "+e.getMessage());
e.printStackTrace();
}
return baos;
}
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String v_report_url = "";
boolean view_only = false;
//This output stream will be the carrier for the .PDF file.
ServletOutputStream out = response.getOutputStream();
ByteArrayOutputStream doc = null;
try
{
//URL to Reports Server Servlet passed by the calling application.
//The URL could actually point to any .PDF doc accessible via HTTP.
v_report_url = request.getParameter("p_report_url");
}
catch(Exception e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
if(v_report_url.length()>0)
{
//Pass the altered document back to the requesting browser or application.
doc = getDoc(v_report_url);
response.setContentType(CONTENT_TYPE);
response.setContentLength(doc.size());
doc.writeTo(out);
doc.close();
out.flush();
}else{
out.println("No Data");
out.close();
}
}
}
10:59:20 AM
|