Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read BLOB (PDF Content) from database and edit and output PDF edited file without creating physical file

I am using an Oracle Database and storing PDF content in a BLOB field.

I want to read the BLOB content and then edit and output the edited content.

The editing I need to do are:

  • add a title above the BLOB content
  • add a Water mark on every page
  • add footer on every page

Then I need to output the file without any physical file getting created that is within the response stream.

I tried to achieve this using itext but was not reaching anywhere with it. I am stuck and not sure where to start with.

Also sometimes I might have to combine blob contents into one, buts thats some thing that is bound to happen Once in a million..so that not a concern now...

How can I achieve my primary requirements of the above three steps using in java? Is it possible with Itext?? Or is some other library available that would help?

Database : Oracle 10g Release 2

OS: Linux Fedora/Redhat

Front-end: Java/Servlet/JSP

EDIT

Here is what I tried to do

oracle.sql.BLOB blob = (BLOB) rs.getBlob("MYPDF");
byte[] bytes = blob.getBytes(1, (int) blob.length());
InputStream is = blob.getBinaryStream();
Document document=new Document();
ServletOutputStream servletOutputStream = response.getOutputStream();
PdfWriter writer=PdfWriter.getInstance(document, servletOutputStream);
document.open();
document.add(new Paragraph("Some title"));
document.add(new Paragraph("Some title"));
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=output.pdf");
servletOutputStream.write(bytes, 0, bytes.length);
servletOutputStream.flush();
servletOutputStream.close();
document.close();

The program outputs the pdf content in BLOB field in the database and without the title.

and when I change a bit in the code (change the order of the last few lines) to:

document.close();
servletOutputStream.flush();
servletOutputStream.close();

I get the document with the title content in it and no pdf content of BLOB field. Its the first thing(servletoutputstream/document) that is closed is been thrown as the output.

And when I closed the document before putting the blob content in outputstream:

document.close();
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=output.pdf");
servletOutputStream.write(bytes, 0, bytes.length);
servletOutputStream.flush();
servletOutputStream.close();

I got the browser displaying something like this:

%PDF-1.4 %���� 2 0 obj <>stream x�+�r �26S�00SI�2P�5��1���BҸ4��sSJ2KrR5C��*P�B�5�+��k)&� endstream endobj 4 0 obj <<<>>>/MediaBox[0 0 595 842]>> endobj 1 0 obj <> endobj 3 0 obj <> endobj 5 0 obj <> endobj 6 0 obj <> endobj xref 0 7 0000000000 65535 f 0000000304 00000 n 0000000015 00000 n 0000000392 00000 n 0000000147 00000 n 0000000443 00000 n 0000000488 00000 n trailer <]/Info 6 0 R/Size 7>> startxref 620 %%EOF 

I need the file to be outputted with the pdf content and the title as well.

Hope this edit helps a little bit...

UPDATE(File thrown out in response with the title and the BLOB Content) :

Document document = new Document(PageSize.A4, 108, 72, 30, 72);
PdfWriter writer = PdfWriter.getInstance(document, outputstream);

document.open();

///-----Added Some Title----///

rs = stmt.executeQuery(queryToGetBLOBCONTENT);

if (rs.next()) {


response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=watermark.pdf");
oracle.sql.BLOB blob = (BLOB) rs.getBlob("MYPDF");
byte[] bytes = blob.getBytes(1, (int) blob.length());
InputStream is = blob.getBinaryStream();
PdfReader pdfReader = new PdfReader(is, bytes);
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
PdfImportedPage page;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
    if (pageOfCurrentReaderPDF > 0) {
        document.newPage();
    }
    pageOfCurrentReaderPDF++;
    currentPageNumber++;
    page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
    cb.addTemplate(page, 0, 0);
}
pageOfCurrentReaderPDF = 0;
outputstream.flush();
document.close();
outputstream.close();

}

This gives me a file in response that has a the BLOB from DB with title on the top and that is done without any physical files getting generated.

Now to generate the water mark and I need to pass the document to the PDfreader how can I achieve that before closing the document (i.e. executing document.close() , which would out put the file w/o water mark as the stream got closed)

What am I doing wrong in this code? How can I achieve the same file with the watermark and that too without a file getting created at the background.

like image 995
Sangeet Menon Avatar asked Mar 28 '11 06:03

Sangeet Menon


People also ask

How do you extract blob from a table and save it as a file?

First we create a directory object pointing to the destination directory. CONN / AS SYSDBA CREATE OR REPLACE DIRECTORY BLOBS AS '/tmp/'; GRANT READ, WRITE ON DIRECTORY BLOBS TO my_user; Next we open the BLOB, read chunks into a buffer and write them to a file. Finally, you can check the file is produced correctly.

Can pdf be blob?

PDFs can be loaded from- and saved-to files, streams and binary arrays. All of which can work with blob storage.

Can we store PDF in Oracle database?

Use Apex - Storing a PDF into an Oracle table is easy if you use APEX. This uses the wwv_flow_files Apex utility to make it simple to store PDF's and other images into Oracle table columns.


1 Answers

If you don't want to create temporary files, then you just need to get the PDF as an InputStream from the DB and let iText read from it and finally write to the OutputStream of the response. Your question is actually too broad to give a well-suited answer ("I am not getting anywhere" doesn't give much to work with), so here's a broad answer:

InputStream input = resultSet.getBinaryStream("columnname");
PdfReader reader = new PdfReader(input);
// ...

OutputStream output = response.getOutputStream();
PdfWriter pdfWriter = PdfWriter.getInstance(document, output);
// ...

You can also pass around a ByteArrayOutputStream instead.


Update as per your problems:

  1. You need to set the response headers before you pass the response body to PdfWriter.

    response.setContentType("application/pdf");
    response.setHeader("Content-Disposition", "attachment; filename=output.pdf");
    PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
    // ...
    
  2. Get rid of the following lines. They would only messup things.

    byte[] bytes = blob.getBytes(1, (int) blob.length());
    servletOutputStream.write(bytes, 0, bytes.length);
    servletOutputStream.flush();
    servletOutputStream.close();
    

    The PdfWriter will already write to the response body. You don't need to repeat it yourself.

like image 111
BalusC Avatar answered Sep 25 '22 04:09

BalusC