Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how to put my pdf "file" (actually a byte array) into iText PDF output stream?

5,460 views
Skip to first unread message

stev...@gmail.com

unread,
Oct 24, 2007, 1:22:47 PM10/24/07
to
We are trying to replace an existing Servlet with the "iText"
SilentPrintServlet to accomplish two things: do a silent print of the
pdf to the user's printer, and display the pdf without any menus in a
new browser window. I've got all the plumbing working, I can use iText
document.add(Chunk("HELLO WORLD") to test our proof of concept and it
does everything I need it to do. The problem comes when trying to plug
in our existing, extensive code base that generates a byte[]
containing a complete PDF. The problem comes in figuring out how the
heck I get my byte[] in the right in the right place so it gets
displayed. I tried creating a String from my byte array and into the
output stream instead of my proof-of-concept "HELLO WORLD" String, but
that output as a single wide black band, both on the printer and in
the output window. I thought maybe I could do something with
PdfObject(int type, byte[] bytes)
but I cannot instantiate him, he's an abstract class. So I'm stuck.
Here's my code, can anyone suggest what I'd need to do to get
"output' (a byte array) to output instead of the commented out "HELLO
WORLD" Chunk? I'm so close yet so far away. Thanks in advance for any
help.

byte[] output = generateCOCPDF(); // a complete PDF comes back as a
byte array

ServletOutputStream out = resp.getOutputStream();

Document document = new Document();

ByteArrayOutputStream baos = new ByteArrayOutputStream();

try {

PdfWriter writer = PdfWriter.getInstance(document, baos);

writer.setViewerPreferences( PdfWriter.HideMenubar |
PdfWriter.HideToolbar | PdfWriter.HideWindowUI );

document.open();

writer.addJavaScript("this.print({bUI: false,bSilent:
false,bShrinkToFit: true});" + "\r\n" + "this.closeDoc();");

// document.add(new Chunk("HELLO WORLD!"));

// WHAT CODE CAN I PLUG IN HERE INSTEAD TO TAKE 'output' AND GET HIM
INTO 'out'?

document.close();

}
catch (DocumentException e)
{
e.printStackTrace();
}

resp.setContentType("application/pdf");

resp.setContentLength(baos.size());

baos.writeTo(out);


out.flush();

Bruno Lowagie

unread,
Oct 25, 2007, 3:34:10 AM10/25/07
to
stev...@gmail.com wrote:
> The problem comes when trying to plug
> in our existing, extensive code base that generates a byte[]
> containing a complete PDF. The problem comes in figuring out how the
> heck I get my byte[] in the right in the right place so it gets
> displayed. I tried creating a String from my byte array and into the
> output stream instead of my proof-of-concept "HELLO WORLD" String,

Er... Using a PDF byte array as a String with iText's high level
objects, wouldn't that result in the PDF syntax being written to
a PDF page instead of being rendered (as is the purpose of PDF
syntax). Don't you see stuff like:

%PDF-1.1
%вгПУ
2 0 obj <</Length 55>>stream
q
BT
36 806 Td
0 -18 Td
/F1 12 Tf
(Hello World)Tj
ET
Q
endstream
endobj

Instead of, for instance, just "Hello World"?

> I thought maybe I could do something with
> PdfObject(int type, byte[] bytes)

No, no, no, who told you that would be a good idea?
Please read the documentation, and you'll find out you
need PdfReader to read the bytes of an existing PDF,
and import complete pages for reuse in a new PDF.

Please read chapter 2 of the book on iText:
http://itext.ugent.be/itext-in-action/
br,
Bruno

stev...@gmail.com

unread,
Oct 25, 2007, 8:23:09 AM10/25/07
to
On Oct 25, 3:34 am, Bruno Lowagie <bruno.lowa...@ugent.be> wrote:

> steveg...@gmail.com wrote:
> > The problem comes when trying to plug
> > in our existing, extensive code base that generates a byte[]
> > containing a complete PDF. The problem comes in figuring out how the
> > heck I get my byte[] in the right in the right place so it gets
> > displayed. I tried creating a String from my byte array and into the
> > output stream instead of my proof-of-concept "HELLO WORLD" String,
>
> Er... Using a PDF byte array as a String with iText's high level
> objects, wouldn't that result in the PDF syntax being written to
> a PDF page instead of being rendered (as is the purpose of PDF
> syntax). Don't you see stuff like:
>
> %PDF-1.1
> %âãÏÓ

> 2 0 obj <</Length 55>>stream
> q
> BT
> 36 806 Td
> 0 -18 Td
> /F1 12 Tf
> (Hello World)Tj
> ET
> Q
> endstream
> endobj
>
> Instead of, for instance, just "Hello World"?
>
> > I thought maybe I could do something with
> > PdfObject(int type, byte[] bytes)
>
> No, no, no, who told you that would be a good idea?
> Please read the documentation, and you'll find out you
> need PdfReader to read the bytes of an existing PDF,
> and import complete pages for reuse in a new PDF.
>
> Please read chapter 2 of the book on iText:http://itext.ugent.be/itext-in-action/
> br,
> Bruno

Actually, "HELLO WORLD" comes out just fine, using document.add(new
Chunk("Hello World")). But when
I take my bytearray (which is a completely assembled pdf, generated by
JFO) and create a PdfString out of it using new
PdfString(mybytearray[]), I can't add him as a Chunk, which seems
counterintuitive, but what the heck.

PdfReader was next on my list of things to look at (I stumbled across
it over on the listserv), so I'm glad to hear I'm headed in the right
direction.

stev...@gmail.com

unread,
Oct 25, 2007, 8:55:55 AM10/25/07
to
On Oct 25, 3:34 am, Bruno Lowagie <bruno.lowa...@ugent.be> wrote:
> steveg...@gmail.com wrote:
> > The problem comes when trying to plug
> > in our existing, extensive code base that generates a byte[]
> > containing a complete PDF. The problem comes in figuring out how the
> > heck I get my byte[] in the right in the right place so it gets
> > displayed. I tried creating a String from my byte array and into the
> > output stream instead of my proof-of-concept "HELLO WORLD" String,
>
> Er... Using a PDF byte array as a String with iText's high level
> objects, wouldn't that result in the PDF syntax being written to
> a PDF page instead of being rendered (as is the purpose of PDF
> syntax). Don't you see stuff like:
>
> %PDF-1.1
> %âãÏÓ

> 2 0 obj <</Length 55>>stream
> q
> BT
> 36 806 Td
> 0 -18 Td
> /F1 12 Tf
> (Hello World)Tj
> ET
> Q
> endstream
> endobj
>
> Instead of, for instance, just "Hello World"?
>
> > I thought maybe I could do something with
> > PdfObject(int type, byte[] bytes)
>
> No, no, no, who told you that would be a good idea?
> Please read the documentation, and you'll find out you
> need PdfReader to read the bytes of an existing PDF,
> and import complete pages for reuse in a new PDF.
>
> Please read chapter 2 of the book on iText:http://itext.ugent.be/itext-in-action/
> br,
> Bruno

Bruno, I just put in an order for "iText in Action." It looks like
we'll need iText's capability for a lot of things, not just this one
item I'm coding up. In the meantime, I wanted to show the bosses some
forward motion on the thing I'm working on, so please help me over
this final hump. OK, I am using SilentPrintServlet, and it's working
great with my "HELLO WORLD" placeholder text:
document.add(new Chunk("HELLO WORLD"));
The output goes to the output page, and also under the covers it goes
to the printer. Everything is beautiful. Now, I need to stop sending
this placeholder text and send me real byte array, which I'm calling
'output[]'. This is a known-good byte array that when our existing
servlet dumps it as-is to a web window (with of course
resp.setContentType("application/pdf") heading it up), it pops up as a
perfect Adobe PDF file inside Adobe Reader. So we know that output[]
is well-formed etc. All we need to accomplish then is to get this
output to go to the printer and the screen, the same way "HELLO WORLD"
does. Should be a simply process, but apparently not. I imagine once I
get the book in hand I'll have a lot more to work with, but for right
now, I have my Document, PdfWriter, etc:


Document document = new Document();

ByteArrayOutputStream baos = new ByteArrayOutputStream(32768);


PdfWriter writer = PdfWriter.getInstance(document, baos);
writer.setViewerPreferences( PdfWriter.HideMenubar |
PdfWriter.HideToolbar | PdfWriter.HideWindowUI );
document.open();
writer.addJavaScript("this.print({bUI: false,bSilent:
false,bShrinkToFit: true});" + "\r\n" + "this.closeDoc();");

All basical boilerplate stuff. Now, what I do currently (and which
works) is:
document.add(new Chunk("HELLO WORLD"));

So I no longer want to send this, I want to send my byte array. So I
have added these lines of code:
PdfReader pdfR = new PdfReader(output);
PdfStamper pdfSt = new PdfStamper(pdfR, baos);

Now what? I need to add what's in pdfR and nothing else and have that
go to printer and screen. So I assume it has to be gotten into
'document' somehow. 'document' definitely wants at least on thing
added, or he complains about it. But I see no way to add a PdfReader
(or his contents) to 'document' and so see no way to get my byte array
outputted to printer and screen.

What piece am I missing here? Thanks in advance.


Hans-Werner Hilse

unread,
Oct 25, 2007, 9:14:53 AM10/25/07
to
Hi,

On Thu, 25 Oct 2007 12:55:55 -0000 stev...@gmail.com wrote:

> Now, I need to stop sending
> this placeholder text and send me real byte array, which I'm calling
> 'output[]'. This is a known-good byte array that when our existing
> servlet dumps it as-is to a web window (with of course
> resp.setContentType("application/pdf") heading it up), it pops up as a
> perfect Adobe PDF file inside Adobe Reader. So we know that output[]
> is well-formed etc.

But you somehow have the misconception about this being related to some
concept you describe as "strings". In fact, you're talking about a
valid PDF, period. How that is being stored is very irrelevant as long
as you can access it. Your wording makes it difficult to understand
what you want to do.



> So I no longer want to send this, I want to send my byte array. So I
> have added these lines of code:
> PdfReader pdfR = new PdfReader(output);
> PdfStamper pdfSt = new PdfStamper(pdfR, baos);
>
> Now what? I need to add what's in pdfR and nothing else and have that
> go to printer and screen. So I assume it has to be gotten into
> 'document' somehow.

Not at this point. And it usually doesn't go to the (high-level
abstraction) "document", but rather some ContentByte container.

> 'document' definitely wants at least on thing
> added, or he complains about it. But I see no way to add a PdfReader
> (or his contents) to 'document' and so see no way to get my byte array
> outputted to printer and screen.

I think you should really read some examples from the tutorial:
http://itextdocs.lowagie.com/tutorial/ or more specifically:
http://itextdocs.lowagie.com/tutorial/general/copystamp/index.php

It seems you just need the PdfStamper in order to add the javascript to
the existing PDF.

-hwh

stev...@gmail.com

unread,
Oct 25, 2007, 10:20:52 AM10/25/07
to
On Oct 25, 9:14 am, Hans-Werner Hilse <hi...@web.de> wrote:
> Hi,
>
> I think you should really read some examples from the tutorial:http://itextdocs.lowagie.com/tutorial/or more specifically:http://itextdocs.lowagie.com/tutorial/general/copystamp/index.php

>
> It seems you just need the PdfStamper in order to add the javascript to
> the existing PDF.
>
> -hwh

Sorry for my inability to articulate the issues clearly, I just
stumbled across iText yesterday so I'm still trying to figure out what
the questions are, never mind the answers. ;)

So it sounds like you're saying I can stuff Javascript into PdfStamper
to replace this code I have now?


writer.addJavaScript("this.print({bUI: false,bSilent:
false,bShrinkToFit: true});" + "\r\n" + "this.closeDoc();");

But I also want to turn off the menu/toolbar items when I display the
PDF in a browser window. I currently achieve that
by doing this:


writer.setViewerPreferences( PdfWriter.HideMenubar |
PdfWriter.HideToolbar | PdfWriter.HideWindowUI );

If I can achieve that by poking PdfStamper also, then it sounds like I
can stuff whatever I need into the PdfStamper and then after I do my
close() calls on everything, my output will go to screen and printer
without any further complexity?


stev...@gmail.com

unread,
Oct 25, 2007, 10:47:03 AM10/25/07
to
> > I think you should really read some examples from the tutorial:http://itextdocs.lowagie.com/tutorial/ormore specifically:http://itextdocs.lowagie.com/tutorial/general/copystamp/index.php

>
> > It seems you just need the PdfStamper in order to add the javascript to
> > the existing PDF.
>
> > -hwh
>
> Sorry for my inability to articulate the issues clearly, I just
> stumbled across iText yesterday so I'm still trying to figure out what
> the questions are, never mind the answers. ;)
>
> So it sounds like you're saying I can stuff Javascript into PdfStamper
> to replace this code I have now?
> writer.addJavaScript("this.print({bUI: false,bSilent:
> false,bShrinkToFit: true});" + "\r\n" + "this.closeDoc();");
>
> But I also want to turn off the menu/toolbar items when I display the
> PDF in a browser window. I currently achieve that
> by doing this:
> writer.setViewerPreferences( PdfWriter.HideMenubar |
> PdfWriter.HideToolbar | PdfWriter.HideWindowUI );
>
> If I can achieve that by poking PdfStamper also, then it sounds like I
> can stuff whatever I need into the PdfStamper and then after I do my
> close() calls on everything, my output will go to screen and printer
> without any further complexity?

I found the addViewerPreference method for PdfStamper, it would appear
to do exactly what I need in terms of turning off menubar etc.

Bruno Lowagie

unread,
Oct 25, 2007, 10:48:12 AM10/25/07
to
stev...@gmail.com wrote:
> If I can achieve that by poking PdfStamper also, then it sounds like I
> can stuff whatever I need into the PdfStamper and then after I do my
> close() calls on everything, my output will go to screen and printer
> without any further complexity?

Have a look at the methods in PdfStamper:
http://itext.ugent.be/library/api/com/lowagie/text/pdf/PdfStamper.html
You have an addJavaScript method, a setViewerPreferences method,
so you're definitely on the right track if you start with this;

PdfReader pdfR = new PdfReader(output);
PdfStamper pdfSt = new PdfStamper(pdfR, baos);

Then do:
pdfSt.addJavaScript("this.print(false);");
pdfSt.setViewerPreferences( PdfWriter.HideMenubar |
PdfWriter.HideToolbar | PdfWriter.HideWindowUI);
pdfSt.close();

once close() is invoked, you can send the content
of the baos to the OutputStream of the ServletResponse.
br,
Bruno

stev...@gmail.com

unread,
Oct 25, 2007, 1:25:45 PM10/25/07
to
On Oct 25, 10:48 am, Bruno Lowagie <bruno.lowa...@ugent.be> wrote:

Thanks, Bruno. I actually got it working while everyone else was off
at lunch, so I could show it off when they returned. ;-) My solution
wound up being pretty much verbatim to what you posted:

PdfBoolean yes = new PdfBoolean(true);
PdfReader pdfR = new PdfReader(output); // 'output' is my byte
array
PdfStamper pdfSt = new PdfStamper(pdfR, out);
pdfSt.addJavaScript("this.print({bUI: false,bSilent:


false,bShrinkToFit: true});" + "\r\n" + "this.closeDoc();");

pdfSt.addViewerPreference(PdfName.HIDETOOLBAR, yes);
pdfSt.addViewerPreference(PdfName.HIDEMENUBAR, yes);
pdfSt.addViewerPreference(PdfName.HIDEWINDOWUI, yes);
// I forgot I could stack those ViewerPreferences using '|' ... :)
pdfR.close();
pdfSt.close();

It works phenomenally well, exactly the way they want it to. I get to
be a hero today. Looking forward to getting my paws on the book to see
what other stuff we can do (PDF output is our bread and butter, so I
suspect we'll get a lot of value from iText).

Thanks again to all for your help.

0 new messages