我有很多pdf文件,我必须将所有pdf合并到一个大的pdf文件中并将其渲染到浏览器中。我使用的是itext。使用这个,我能够将pdf文件合并到一个文件到磁盘但我无法合并到浏览器中,浏览器中只有最后一个pdf ..以下是我的代码..请帮助我。
提前致谢。
Document document = new Document();
List<PdfReader> readers =
new ArrayList<PdfReader>();
int totalPages = 0;
ServletOutputStream servletOutPutStream = response.getOutputStream();;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();;
InputStream is=null;
List<InputStream> inputPdfList = new ArrayList<InputStream>();
System.err.println(imageMap.size());
for(byte[] imageList:imageMap)
{
System.out.println(imageList.toString()+" "+imageList.length);
byteArrayOutputStream.write(imageList);
byteArrayOutputStream.writeTo(response.getOutputStream());
is = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
inputPdfList.add(is);
}
response.setContentType("application/pdf");
response.setContentLength(byteArrayOutputStream.size());
System.out.println(inputPdfList.size()+""+inputPdfList.toString());
//Create pdf Iterator object using inputPdfList.
Iterator<InputStream> pdfIterator =
inputPdfList.iterator();
// Create reader list for the input pdf files.
while (pdfIterator.hasNext()) {
InputStream pdf = pdfIterator.next();
PdfReader pdfReader = new PdfReader(pdf);
readers.add(pdfReader);
totalPages = totalPages + pdfReader.getNumberOfPages();
}
// Create writer for the outputStream
PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
//Open document.
document.open();
//Contain the pdf data.
PdfContentByte pageContentByte = writer.getDirectContent();
PdfImportedPage pdfImportedPage;
int currentPdfReaderPage = 1;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Iterate and process the reader list.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
//Create page and add content.
while (currentPdfReaderPage <= pdfReader.getNumberOfPages()) {
document.newPage();
pdfImportedPage = writer.getImportedPage(
pdfReader,currentPdfReaderPage);
pageContentByte.addTemplate(pdfImportedPage, 0, 0);
currentPdfReaderPage++;
}
currentPdfReaderPage = 1;
}
//Close document and outputStream.
servletOutPutStream.flush();
outputStream.flush();
document.close();
outputStream.close();
servletOutPutStream.close();
System.out.println("Pdf files merged successfully.");
答案 0 :(得分:2)
您的代码中存在许多错误:
您的代码将大量数据写入响应输出流:
ServletOutputStream servletOutPutStream = response.getOutputStream();;
[...]
for(byte[] imageList:imageMap)
{
[...]
byteArrayOutputStream.writeTo(response.getOutputStream());
[...]
}
[...]
PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
[... merge PDFs into the writer]
servletOutPutStream.flush();
document.close();
servletOutPutStream.close();
这会导致要在那里写入imageMap
个元素的许多副本,并且此后才会添加合并文件。
您希望浏览器做什么,忽略所有主要的源PDF副本,直到最终合并的PDF出现?
因此,请仅将合并的PDF写入响应输出流。
最好将内容长度写入响应... ,但前提是您使用正确的值!
在你的代码中你写了一个内容长度:
response.setContentLength(byteArrayOutputStream.size());
但此时byteArrayOutputStream
仅包含源PDF的副本,而不是最终合并的PDF。因此,这只会使浏览器更加混乱。
因此,请不要在回复中添加错误的标头。
在循环中
for(byte[] imageList:imageMap)
{
System.out.println(imageList.toString()+" "+imageList.length);
byteArrayOutputStream.write(imageList);
byteArrayOutputStream.writeTo(response.getOutputStream());
is = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
inputPdfList.add(is);
}
你接受byte
数组,我假设每个数组包含一个源PDF,用它们污染响应输出流(如前所述),并创建一个输入流集合,其中第一个包含第一个源PDF ,第二个包含前两个源PDF的串联,第三个前三个源PDF的串联等...
因为你永远不会重置或重新实例化byteArrayOutputStream
,所以它只会变得越来越大。
因此,请通过重置byteArrayOutputStream
来开始或结束此类循环。
(实际上你根本不需要那个循环,PdfReader
有一个构造函数,可以立即获取byte[]
,不需要将它包装在字节流中。)
PdfWriter
合并PDF,请使用PdfCopy
您使用PdfWriter
/ getImportedPage
/ addTemplate
方法合并PDF。关于堆栈溢出有很多问题和答案(其中很多都是由iText开发人员回答的)解释说这通常是一个坏主意,你应该使用PdfCopy
。
因此,请在此处使用此主题中已存在的许多好答案,并使用PdfCopy
进行合并。
通过关闭众多流来最终确定响应输出:
//Close document and outputStream.
servletOutPutStream.flush();
outputStream.flush();
document.close();
outputStream.close();
servletOutPutStream.close();
我没有看到你声明或设置outputStream
变量的行,但即使它包含响应输出流,也没有必要关闭它,因为你已经在{{1变量。
因此,请删除此类不必要的电话。