I have been searching for days for a solution to this problem.
Description : I have a website which loads a PDF dynamically via an iFrame. The PDF is saved on the server and the user of the website can view the pdf on the website.
Problem : Introduce a Print button on website which prints the PDF which was created dynamically and saved on the server.
Is this even possible ? I am looking at a cross-browser implementation as well to make things worse. I have tried n number of JS options from the web but none of them seem to work. I can not seem to get the PDF printed in the same way as it looks. To put it short, I am trying to emulate the print button which appears on the PDF when it is loaded. Is there an option to pass the pdf document from the server to the print dialog box ?
Description : I have a website which loads a PDF dynamically via an iFrame. The PDF is saved on the server and the user of the website can view the pdf on the website.
Problem : Introduce a Print button on website which prints the PDF which was created dynamically and saved on the server.
Solution : I could not find an exact solution to this problem, but here is how I solved the problem -
Create the 'Print' as per req and redirect that to another page which has only the PDF.
Copy the previous PDF & Create new PDF with JS - this.print() such that when it opens up, the print dialog pops up directly to the user.
In the new page -
if ("Location of PDF " != null)
{
sPdf = "Location of PDF ";
PdfReader pReader = new PdfReader(sPdf);
Document document = new Document
(pReader.GetPageSizeWithRotation(ApplicationConstants.INDEX_ONE));
int n = pReader.NumberOfPages;
FileStream fs = new FileStream
("New PDF location",
FileMode.Create, FileAccess.Write);
PdfCopy copy = new PdfCopy(document, fs);
// Write to pdf
document.Open();
for (int i = ApplicationConstants.INDEX_ONE; i <= n; i++)
{
PdfImportedPage page = copy.GetImportedPage(pReader, i);
copy.AddPage(page);
}
copy.AddJavaScript("this.print(true);", true);
document.Close();
pReader.Close();
inStr = File.OpenRead("New PDF location");
while ((bytecnt = inStr.Read
(buffer, ApplicationConstants.INDEX_ZERO, buffer.Length))
> ApplicationConstants.INDEX_ZERO)
{
if (Context.Response.IsClientConnected)
{
Context.Response.ContentType = "application/PDF";
Context.Response.OutputStream.Write(buffer,
ApplicationConstants.INDEX_ZERO, buffer.Length);
Context.Response.Flush();
}
}
}
Please note that I am using itextsharp to inject the JS script into the new PDF. Hope this helps someone else. I am trying to find another solution without the usage of itextsharp or any other dll but this will have to do for now.
I am not sure if this will work, but you could try launching a popup window with a special version of your PDF file that opens the print dialog when opened. Then close the popup afterwards. This last part might be tricky since I think there is no clean way to know if the print dialog has been closed.
Related
I am currently evaluating iTextSharp for potential use in a project. The code that I have written to achieve my goal is making use of PDFCopy.GetImportedPage to copy all of the pages from an existing PDF. What I want to know is what all do I need to be aware of that will be lost from a PDF and/or page when duplicating PDF content like this? For example, one thing that I already noticed is that I need to manually add in any bookmarks and named destinations into my new PDF.
Here's some rough sample code:
using (PdfReader reader = new PdfReader(inputFilename))
{
using (MemoryStream ms = new MemoryStream())
{
using (Document document = new Document())
{
using (PdfCopy copy = new PdfCopy(document, ms))
{
document.Open();
int n;
n = reader.NumberOfPages;
for (int page = 0; page < n; )
{
copy.AddPage(copy.GetImportedPage(reader, ++page));
}
// add content and make further modifications here
}
}
// write the content to disk
}
}
Basically anything that's document-level instead of page-level will get lost and both Bookmarks and Destinations are document-level. Pull up the PDF spec and look at section 3.6.1 for other entries in the document catalog including Threads, Open and Additional Actions and Meta Data.
You might already have seen these but here are some samples (in Java) of how to merge Named Destinations and how to merge Bookmarks.
BACKGROUND
I have a java program that analyzes data and creates a pdf report using itext 5.
I recently had to add a summary of major problems at the start of the document so a user would not have to read over a hundred pages to find problems. Problems are only discovered when serially looking through the data.
I solved the problem by creating 3 pdf documents and then merging them, a start/title pdf, the summary of problems pdf, and the body or analysis pdf. (Basically splitting the original document at the point I wanted to insert the summary)
I use PdfReader and PdfCopy to combine the documents. I am able to keep the chapter bookmarks OK.
THE PROBLEM
As I encounter a significant problem I add it to the 'summary' document. I want to add a link in the summary to point to the problem in the body.
I tried to use Chunk.setLocalDestination and setLocalGoto but realized why that did not work, so I tried using setLocalDestination and setRemoteGoto (with and without 'file://'), but that did not work either. (Also, I used the final pdf document name in the RemoteGoto, not the temporary pdf document name.)
I do not want to use bookmarks because that seems wrong and would not look right.
I am hoping someone could suggest an alternate method or make a suggestion.
To recap, in my current code a create a Chunk with setLocalDestination and that chunk goes into the 'body' document. At the same time I create a setRemoteGoto which is put into the summary document. I was hoping when they were combined the link would work, but when the link is clicked, you go to the first page of the combined document.
Thanks.....
PS I have both iText in action books
CLARIFICATION 3/5/2014
What I was calling 'bookmarks' are really Chapter class entities that are inserted into sections of the 3 documents as they are being created.
After saving the 3 documents, PdfReader is used to open each and PdfCopy is used to put them into a new, final document.
I get the data from the Chapters, which creates the 'bookmarks' on the left side of the Pdf reader used by the user, e.g. Acrobat Reader.
int thisPdfPages = reader.getNumberOfPages();
reader.consolidateNamedDestinations();
java.util.List<HashMap<String, Object>> bookmarks = SimpleBookmark.getBookmark(reader);
if (bookmarks != null) {
if (pageOffset != 0) {
if (debug3) auditLogger.log("Shifting pages by " + pageOffset );
SimpleBookmark.shiftPageNumbers(bookmarks, pageOffset, null);
}
masterBookmarks.addAll(bookmarks);
}
for (int i = 0; i < thisPdfPages;) {
page = copy.getImportedPage(reader, ++i);
stamp = copy.createPageStamp(page);
// add page numbers
ColumnText.showTextAligned(stamp.getUnderContent(), Element.ALIGN_CENTER, new Phrase(String.format("page %d of %d", start + i, totalPages)), 297.5f, 28, 0);
stamp.alterContents();
copy.addPage(page);
}
PRAcroForm form = reader.getAcroForm();
if (form != null) {
copy.copyAcroForm(reader);
}
When analyzing the data I have 2 documents open, a base document which contains all the details and a summary document which contains notable events over some thresholds.
//NOTE section is part of the 'body' document
//NOTE summaryPhrase is a part of the 'summary' document
String linkName = "summaryPf_" + networkid ;
//create Link target
section.add(new Chunk("CHANGE TO EMPTY STRING WHEN WORKING").setLocalDestination( linkName ));
//create Link
Chunk linkChunk = new Chunk( "[Link] " );
Font linkFont = new Font( regularFont );
linkFont.setColor(BaseColor.BLUE);
linkFont.setStyle( Font.UNDERLINE );
linkChunk.setFont( linkFont );
boolean useLocal = true;
// both local and remote goto's fail
if (useLocal) {
linkChunk.setLocalGoto( linkName);
} else {
// all permutations of setting filename fail,
// but it does bring up a permissions dialog when the link is clicked.
//String remotePdfName = "file://./" + pdfReportName ;
//String remotePdfName = "file://" + pdfReportName ;
//String remotePdfName = "file:" + pdfReportName ;
String remotePdfName = pdfReportName ;
linkChunk.setRemoteGoto( remotePdfName, linkName);
}
// add link to summary document
summaryPhrase.add( linkChunk );
summaryPhrase.add( String.format("There were %d devices with ping failures", summaryCount));
summaryPhrase.add( Chunk.NEWLINE );
}
If I use setLocalGoto, when you click the link in the final document you goto the first page.
If I use setRemoteGoto, a dialog ask permission to go to a document, but the document fails to open, tried several permutations on filename.
I have a requirement in which I have to generate a pdf and then on click of button "SHOW PDF", I have to display on another window.
I have been able to generate a pdf using IText and stored in my machine. I get a java.io.File object as my return value from my backend library which needs to be displayed on the screen. Can someone please guide me how to do this?
My xhtml file has the following code snippet:
<h:commandLink action="PdfDisplayRedirect.xhtml" target="_blank">show PDF</h:commandLink>
my PdfDisplayRedirect.xhtml has the following code:
<p:media value="#{pdfGenerationAction.fileName}" width="100%" height="300px">
Your browser can't display pdf, <h:outputLink value="InitialExamination33.pdf">click</h:outputLink> to download pdf instead.
My backing bean has the following code:
private File initialExaminationFile;
private generateFile(){
this.initialExaminationFile = backendService.generateFile();
}
On clicking, I get a new window opened but the pdf file is not displayed.. Instead my screen from where I had invoked the command gets displayed there.
Any help would be really appreciated.
Thanks
Thanks for the response and no response.
I have found a solution myself which I would like to post so that those looking for a solution can use it.
My xhtml file included a commandlink
<p:commandLink actionListener="#{pdfGenerationAction.generatePDF(initialExaminationEMRAction.patientID)}" oncomplete="window.open('PdfDisplayRedirect.xhtml')">broadcast Msg</p:commandLink>
My pdfGenerationAction bean file had the following lines of code:
FileInputStream fis = new FileInputStream(this.initialExaminationFile);
//System.out.println(file.exists() + "!!");
//InputStream in = resource.openStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = fis.read(buf)) != -1;) {
bos.write(buf, 0, readNum); //no doubt here is 0
//Writes len bytes from the specified byte array starting at offset off to this byte array output stream.
System.out.println("read " + readNum + " bytes,");
}
this.reportBytes = buf;
}
I converted my file into bytearraystream and made it available in my session. Then I followed the suggestion given by BalusC at Unable to show PDF in p:media generated from streamed content in Primefaces
I am trying to automate printing of intranet websites. Since this is an application that will be put on a specific user's computer, which will be run on an as-needed basis, I'd like it to be as un-disruptive as possible (in other words, not launching IE for each page). The catch is that I need to print the first page of the website and then print the whole website again, which will produce the first page two times. What is the best way to do this?
I have no problem getting it to loop through the pages that it needs to print, nor do I have a problem opening the page with webbrowser. I do, however, have a problem specifying a print range.
I also tried PrintDocument, but couldn't figure out how to get that to open within the form.
Thanks for any help that can be provided.
To download the pdf file, try this solution using iTextSharp:
ITextSharp HTML to PDF?
Except with one substitution if you want to save directly to a file
private MemoryStream createPDF(string html)
{
MemoryStream msOutput = new MemoryStream();
TextReader reader = new StringReader(html);
// step 1: creation of a document-object
Document document = new Document(PageSize.A4, 30, 30, 30, 30);
// step 2:
// we create a writer that listens to the document
// and directs a XML-stream to a file
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("c:\\my.pdf", FileMode.Create));
// step 3: we create a worker parse the document
HTMLWorker worker = new HTMLWorker(document);
// step 4: we open document and start the worker on the document
document.Open();
worker.StartDocument();
// step 5: parse the html into the document
worker.Parse(reader);
// step 6: close the document and the worker
worker.EndDocument();
worker.Close();
document.Close();
return msOutput;
}
Once the PDF is set up, try ghostscript to print one page:
Print existing PDF (or other files) in C#
If you start a shell execute of the process, you can use the command line arguments:
gsprint "filename.pdf" -from 1 - to 1
Alternatively, WebBrowser can just print the full page: http://msdn.microsoft.com/en-us/library/b0wes9a3.aspx
I can't find anything referencing that WebBrowser itself can print "From page X to Y" without a print dialog.
Since I'm facing a similar problem, here's an alternate solution:
This open source project turns HTML documents to PDF documents similar to iTextSharp (http://code.google.com/p/wkhtmltopdf/). We ended up not using iTextSharp because of several formatting issues with the way the site we wanted to print was laid out. We send command line arguments to turn the html downloaded using a webclient into a pdf file.
WebClient wc = new WebClient();
wc.Credentials = CredentialCache.DefaultNetworkCredentials;
string htmlText = wc.DownloadString("http://websitehere.com);
Then, after turning to pdf, you can simply print the file:
Process p = new Process();
p.StartInfo.FileName = string.Format("{0}.pdf", fileLocation);
p.StartInfo.Verb = "Print";
p.Start();
p.WaitForExit();
(Apologies for C#, I'm more familiar with it than VB.NET, though it should be a simple conversion)
I pieced together some code to insert a dynamic image into a PDF using both ColdFusion and iText, while filling in some form fields as well. After I got it working and blogged about it, I couldn't help but think that there might be a better way to accomplish this. I'm using the basic idea of this in a production app right now so any comments or suggestion would be most welcomed.
<cfscript>
// full path to PDF you want to add image to
readPDF = expandpath(”your.pdf”);
// full path to the PDF we will output. Using creatUUID() to create
// a unique file name so we can delete it afterwards
writePDF = expandpath(”#createUUID()#.pdf”);
// full path to the image you want to add
yourimage = expandpath(”dynamic_image.jpg”);
// JAVA STUFF!!!
// output buffer to write PDF
fileIO = createObject(”java”,”java.io.FileOutputStream”).init(writePDF);
// reader to read our PDF
reader = createObject(”java”,”com.lowagie.text.pdf.PdfReader”).init(readPDF);
// stamper so we can modify our existing PDF
stamper = createObject(”java”,”com.lowagie.text.pdf.PdfStamper”).init(reader, fileIO);
// get the content of our existing PDF
content = stamper.getOverContent(reader.getNumberOfPages());
// create an image object so we can add our dynamic image to our PDF
image = createobject(”java”, “com.lowagie.text.Image”);
// get the form fields
pdfForm = stamper.getAcroFields();
// setting a value to our form field
pdfForm.setField(”our_field”, “whatever you want to put here”);
// initalize our image
img = image.getInstance(yourimage);
// centering our image top center of our existing PDF with a little margin from the top
x = (reader.getPageSize(1).width() - img.scaledWidth()) - 50;
y = (reader.getPageSize(1).height() - img.scaledHeight()) / 2 ;
// now we assign the position to our image
img.setAbsolutePosition(javacast(”float”, y),javacast(”float”, x));
// add our image to the existing PDF
content.addImage(img);
// flattern our form so our values show
stamper.setFormFlattening(true);
// close the stamper and output our new PDF
stamper.close();
// close the reader
reader.close();
</cfscript>
<!— write out new PDF to the browser —>
<cfcontent type=”application/pdf” file = “#writePDF#” deleteFile = “yes”>
<cfpdf> + DDX seems possible.
See http://forums.adobe.com/thread/332697
I have made it in another way with itext library
I don´t want overwrite my existing pdf with the image to insert, so just modify the original pdf inserting the image, just insert with itext doesn´t work for me.
So, I have to insert the image into a blank pdf (http://itextpdf.com/examples/iia.php?id=59)
And then join my original pdf and the new pdf-image. Obtaining one pdf with several pages.
(http://itextpdf.com/examples/iia.php?id=110)
After that you can overlay the pdf pages with this cool concept
http://itextpdf.com/examples/iia.php?id=113