从数据库中读取BLOB(PDF内容)并编辑和输出PDF编辑的文件,而无需创建物理文件

问题描述:

我正在使用Oracle数据库并将PDF内容存储在BLOB字段中。

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

我想阅读BLOB内容,然后编辑并输出已编辑的内容。

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

我需要做的编辑是:


  • 在BLOB上方添加一个标题内容

  • 在每个页面上添加水印

  • 在每页上添加页脚

然后我需要在响应流中没有创建任何物理文件的情况下输出文件。

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

我试图用itext实现这个目的但是没有到达任何地方。我被困住了,不知道从哪里开始。

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

有时候我可能需要将blob内容合并为一个,但有些事情必然会发生在一个百万...现在不用担心...

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...

如何在java中实现上述三个步骤的主要要求? Itext可以吗?或者是否有其他可用的库?

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?

数据库:Oracle 10g第2版

Database : Oracle 10g Release 2

操作系统:Linux Fedora / Redhat

OS: Linux Fedora/Redhat

前端:Java / Servlet / JSP

Front-end: Java/Servlet/JSP

编辑

这是我试图做的事情

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();

程序在数据库的BLOB字段中输出pdf内容而没有标题。

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();

我收到包含标题内容的文档,没有BLOB字段的pdf内容。
它关闭的第一件事(servletoutputstream / document)被抛出作为输出。

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.

当我在放入blob内容之前关闭文档outputstream:

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();

我的浏览器显示如下:

%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 

我需要输出带有pdf内容和标题的文件。

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

希望这个编辑有所帮助......

Hope this edit helps a little bit...

UPDATE(文件被抛出回复标题和BLOB内容):

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();

}

这给了我一个响应的文件,它有一个BLOB来自顶部有标题的数据库,并且没有生成任何物理文件。

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.

现在生成水印,我需要将文档传递给PDfreader如何我可以在关闭文档之前实现这一点(即执行 document.close(),这会在文件流关闭时将文件放在水印上)

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.

而不是写作直接到servletOutputStream,您可以尝试这种方法:

Instead of writing directly to servletOutputStream, you can try this approach:


  1. 创建ByteArrayOutputStream的实例

  2. 创建实例合并PDF文件。即PDF格式Blob + PDF有标题。此示例可能有所帮助: http:// java- x.blogspot.com/2006/11/merge-pdf-files-with-itext.html

  3. 将合并的PDF写入ByteArrayOutputStream的实例

  4. 设置内容响应长度

  5. 设置内容类型和内容处理

  6. 从ByteArrayOutputStream获取字节并将这些字节写入servletOutputStream

  7. 关闭ByteArrayOutputStream

  1. Create an instance of ByteArrayOutputStream
  2. Create instance of "merged" PDF document. I.e. PDF form Blob + PDF that has title. This example might help : http://java-x.blogspot.com/2006/11/merge-pdf-files-with-itext.html
  3. Write the merged PDF to instance of ByteArrayOutputStream
  4. Set content length of response
  5. Set content type and content disposition
  6. Get bytes from ByteArrayOutputStream and write those bytes to servletOutputStream
  7. Close ByteArrayOutputStream