包含 PDDoucment 的问题
Issues with enclosing PDDoucment
我已经实现了一个将数据打印成 pdf 的程序,但是我遇到了这个问题
java.io.IOException: COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?
我知道已经发布了类似的问题,但我无法从他们那里找到解决我的问题的方法。我正在做的是我初始化了两个文档,其中一个是主文档(doc),另一个是其余页面,然后我添加到主文档(activeDocument),该服务调用三个不同的函数来添加一个新的第一页第一页,中间的任何页面,最后一页之前和最后一页 page.a 这是我的代码,大部分逻辑都可以忽略,主要是与 PDDocuments 相关的内容,因为那是问题所在
private InputStream generateCardsPDF(String cardNumber,
String generationDate,
StatementSummaryResTypeStatementSummaryResBody resBody,
String pdf) throws IOException, ParseException {
List<StatementSummaryResTypeStatementSummaryResBodyTransactionsTransaction> transactionList = resBody.getTransactions().getTransaction().stream().limit(50).collect(Collectors.toList());
PDDocument doc = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
PDDocumentCatalog docCatalog = doc.getDocumentCatalog();
PDPage page = docCatalog.getPages().get(0);
try {
String fullName = resBody.getStatementHeader().getAddress().getTitle() +
" " + resBody.getStatementHeader().getAddress().getFirstName() + " ";
String fullAddress = "";
if (resBody.getStatementHeader().getAddress().getMiddleName() != null) {
fullName = fullName + resBody.getStatementHeader().getAddress().getMiddleName() + " ";
}
fullName = fullName + resBody.getStatementHeader().getAddress().getLastName();
String countryAddress = resBody.getStatementHeader().getAddress().getCity() != null ? resBody.getStatementHeader().getAddress().getCity() : "";
countryAddress += resBody.getStatementHeader().getAddress().getCountry() != null &&
countryAddress.length() > 0 ? ", " + resBody.getStatementHeader().getAddress().getCountry() : "";
countryAddress += resBody.getStatementHeader().getAddress().getCountry() != null &&
countryAddress.length() == 0 ? resBody.getStatementHeader().getAddress().getCountry() : "";
fullAddress += resBody.getStatementHeader().getAddress().getAddress1() + ONE_LINE;
fullAddress += resBody.getStatementHeader().getAddress().getAddress2() != null ? resBody.getStatementHeader().getAddress().getAddress2() + ONE_LINE : "";
fullAddress += resBody.getStatementHeader().getAddress().getAddress3() != null ? resBody.getStatementHeader().getAddress().getAddress3() + ONE_LINE : "";
fullAddress += countryAddress;
String header = fullName + ONE_LINE + fullAddress;
Integer currentIndex = 0;
Integer count = 0;
Integer cutOff = 0;
Integer pageNumber = 1;
Integer numberOfPages = statementsUtils.calculateNumberOfPages(transactionList, currentIndex, cutOff, count);
String pageOf;
PDDocument activeDocument = new PDDocument();
statementsUtils.setFirstPage(transactionList, resBody, doc, header, maskedCard(cardNumber), generationDate, numberOfPages);
try {
while (currentIndex < transactionList.size()) {
Boolean fourOrFive = false;
Boolean checkpoint = false;
Boolean finalPrint = false;
if (count == 4) {
checkpoint = statementsUtils.reachedCheckpoint(currentIndex, transactionList);
if (checkpoint) {
cutOff = currentIndex;
fourOrFive = true;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
count = 0;
}
} else if (count == 5) {
cutOff = currentIndex;
fourOrFive = false;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
count = 0;
} else if (transactionList.size() <= 2) {
finalPrint = true;
} else if (transactionList.size() - currentIndex + 1 <= 5) { // count <4? print last page or count >=4 print 4 and check homuch left
finalPrint = true;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
if (transactionList.size() - currentIndex + 1 == 5) {
statementsUtils.setPreLastPage(doc, activeDocument, currentIndex, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
statementsUtils.setLastPage(doc, activeDocument, transactionList.size() - 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
} else {
statementsUtils.setLastPage(doc, activeDocument, currentIndex - count + 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
}
}
if (fourOrFive && !finalPrint)
currentIndex = cutOff + 1;
else if (finalPrint)
currentIndex = transactionList.size();
else
currentIndex++;
if (currentIndex >= 2) count++;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (activeDocument != null) {
activeDocument.close();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
PDPageContentStream contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true);
contentStream.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
if (doc != null) {
doc.save(out);
doc.close();
}
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
return in;
}
}
public void setFirstPage( PDDocument doc,....){
PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
...
acroForm.flatten();
}
public void setPreLastPage( PDDocument doc, PDDocument activeDocument....){
activeDocument = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
PDDocumentCatalog docCatalog = activeDocument.getDocumentCatalog();
PDPage p1 = docCatalog.getPages().get(0);
PDAcroForm acroForm = docCatalog.getAcroForm();
...
acroForm.flatten();
PDPageContentStream cs = new PDPageContentStream(activeDocument, p1,PDPageContentStream.AppendMode.APPEND, true);
cs.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
activeDocument.save(out);
doc.addPage(p1);
}
public void setLastPage( PDDocument doc, PDDocument activeDocument....){
activeDocument = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
PDDocumentCatalog docCatalog = activeDocument.getDocumentCatalog();
PDPage p1 = docCatalog.getPages().get(0);
PDAcroForm acroForm = docCatalog.getAcroForm();
...
acroForm.flatten();
PDPageContentStream cs = new PDPageContentStream(activeDocument, p1,PDPageContentStream.AppendMode.APPEND, true);
cs.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
activeDocument.save(out);
doc.addPage(p1);
}
public void addExtraPage( PDDocument doc, PDDocument activeDocument....){
activeDocument = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
PDDocumentCatalog docCatalog = activeDocument.getDocumentCatalog();
PDPage p1 = docCatalog.getPages().get(0);
PDAcroForm acroForm = docCatalog.getAcroForm();
...
acroForm.flatten();
PDPageContentStream cs = new PDPageContentStream(activeDocument, p1,PDPageContentStream.AppendMode.APPEND, true);
cs.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
activeDocument.save(out);
doc.addPage(p1);
}
这些函数中有更多的逻辑,但我尝试只添加我认为相关的内容。
我认为问题与其中一个 pdf 的内容流或我关闭、保存等的顺序有关....但我无法弄清楚确切的问题是什么,所以任何建议都会不胜感激。
三个错误在 setPreLastPage
、setLastPage
和 addExtraPage
中:在这些方法中的每一个中,您在各自的局部变量 [=14] 中加载一个新的 PDDocument
=],从中取出一个页面并将其添加到相同的 PDDocument doc
,然后在离开相应方法时删除 activeDocument
中对该 PDDocument
的所有引用。
删除所有引用允许垃圾回收选择这些 PDDocument
实例并关闭并删除它们。这会拉走复制到 PDDocument doc
的页面下方的数据,导致您在尝试保存 doc
.
时观察到的错误
为防止这种情况,要么在添加页面对象之前将页面对象克隆到 doc
中,要么在保存 doc
.
之前保持所有这些临时文档处于打开状态
如果有人对解决方案的实际实施感到好奇,我创建了一个空列表。
List<PDDocument> activeDocuments = new ArrayList<PDDocument>();
然后每次我调用其中一种方法时,我都会返回文档并将其存储在列表中,然后在保存原始文档后最后将它们全部关闭。
while (currentIndex < transactionList.size()) {
Boolean fourOrFive = false;
Boolean checkpoint = false;
Boolean finalPrint = false;
if (count == 4) {
checkpoint = statementsUtils.reachedCheckpoint(currentIndex, transactionList);
if (checkpoint) {
cutOff = currentIndex;
fourOrFive = true;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
activeDocuments.add(statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
count = 0;
}
} else if (count == 5) {
cutOff = currentIndex;
fourOrFive = false;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
activeDocuments.add(statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
count = 0;
} else if (transactionList.size() <= 2) {
finalPrint = true;
} else if (transactionList.size() - currentIndex + 1 <= 5) { // count <4? print last page or count >=4 print 4 and check homuch left
finalPrint = true;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
if (transactionList.size() - currentIndex + 1 == 5) {
activeDocuments.add(statementsUtils.setPreLastPage(doc, activeDocument, currentIndex, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
activeDocuments.add(statementsUtils.setLastPage(doc, activeDocument, transactionList.size() - 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
} else {
activeDocuments.add(statementsUtils.setLastPage(doc, activeDocument, currentIndex - count + 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
}
}
if (fourOrFive && !finalPrint)
currentIndex = cutOff + 1;
else if (finalPrint)
currentIndex = transactionList.size();
else
currentIndex++;
if (currentIndex >= 2) count++;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
PDPageContentStream contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true);
contentStream.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
if (doc != null) {
doc.save(out);
doc.close();
}
for (PDDocument a : activeDocuments)
a.close();
if (activeDocument != null) {
activeDocument.close();
}
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
return in;
}
我已经实现了一个将数据打印成 pdf 的程序,但是我遇到了这个问题
java.io.IOException: COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?
我知道已经发布了类似的问题,但我无法从他们那里找到解决我的问题的方法。我正在做的是我初始化了两个文档,其中一个是主文档(doc),另一个是其余页面,然后我添加到主文档(activeDocument),该服务调用三个不同的函数来添加一个新的第一页第一页,中间的任何页面,最后一页之前和最后一页 page.a 这是我的代码,大部分逻辑都可以忽略,主要是与 PDDocuments 相关的内容,因为那是问题所在
private InputStream generateCardsPDF(String cardNumber,
String generationDate,
StatementSummaryResTypeStatementSummaryResBody resBody,
String pdf) throws IOException, ParseException {
List<StatementSummaryResTypeStatementSummaryResBodyTransactionsTransaction> transactionList = resBody.getTransactions().getTransaction().stream().limit(50).collect(Collectors.toList());
PDDocument doc = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
PDDocumentCatalog docCatalog = doc.getDocumentCatalog();
PDPage page = docCatalog.getPages().get(0);
try {
String fullName = resBody.getStatementHeader().getAddress().getTitle() +
" " + resBody.getStatementHeader().getAddress().getFirstName() + " ";
String fullAddress = "";
if (resBody.getStatementHeader().getAddress().getMiddleName() != null) {
fullName = fullName + resBody.getStatementHeader().getAddress().getMiddleName() + " ";
}
fullName = fullName + resBody.getStatementHeader().getAddress().getLastName();
String countryAddress = resBody.getStatementHeader().getAddress().getCity() != null ? resBody.getStatementHeader().getAddress().getCity() : "";
countryAddress += resBody.getStatementHeader().getAddress().getCountry() != null &&
countryAddress.length() > 0 ? ", " + resBody.getStatementHeader().getAddress().getCountry() : "";
countryAddress += resBody.getStatementHeader().getAddress().getCountry() != null &&
countryAddress.length() == 0 ? resBody.getStatementHeader().getAddress().getCountry() : "";
fullAddress += resBody.getStatementHeader().getAddress().getAddress1() + ONE_LINE;
fullAddress += resBody.getStatementHeader().getAddress().getAddress2() != null ? resBody.getStatementHeader().getAddress().getAddress2() + ONE_LINE : "";
fullAddress += resBody.getStatementHeader().getAddress().getAddress3() != null ? resBody.getStatementHeader().getAddress().getAddress3() + ONE_LINE : "";
fullAddress += countryAddress;
String header = fullName + ONE_LINE + fullAddress;
Integer currentIndex = 0;
Integer count = 0;
Integer cutOff = 0;
Integer pageNumber = 1;
Integer numberOfPages = statementsUtils.calculateNumberOfPages(transactionList, currentIndex, cutOff, count);
String pageOf;
PDDocument activeDocument = new PDDocument();
statementsUtils.setFirstPage(transactionList, resBody, doc, header, maskedCard(cardNumber), generationDate, numberOfPages);
try {
while (currentIndex < transactionList.size()) {
Boolean fourOrFive = false;
Boolean checkpoint = false;
Boolean finalPrint = false;
if (count == 4) {
checkpoint = statementsUtils.reachedCheckpoint(currentIndex, transactionList);
if (checkpoint) {
cutOff = currentIndex;
fourOrFive = true;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
count = 0;
}
} else if (count == 5) {
cutOff = currentIndex;
fourOrFive = false;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
count = 0;
} else if (transactionList.size() <= 2) {
finalPrint = true;
} else if (transactionList.size() - currentIndex + 1 <= 5) { // count <4? print last page or count >=4 print 4 and check homuch left
finalPrint = true;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
if (transactionList.size() - currentIndex + 1 == 5) {
statementsUtils.setPreLastPage(doc, activeDocument, currentIndex, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
statementsUtils.setLastPage(doc, activeDocument, transactionList.size() - 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
} else {
statementsUtils.setLastPage(doc, activeDocument, currentIndex - count + 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
}
}
if (fourOrFive && !finalPrint)
currentIndex = cutOff + 1;
else if (finalPrint)
currentIndex = transactionList.size();
else
currentIndex++;
if (currentIndex >= 2) count++;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (activeDocument != null) {
activeDocument.close();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
PDPageContentStream contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true);
contentStream.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
if (doc != null) {
doc.save(out);
doc.close();
}
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
return in;
}
}
public void setFirstPage( PDDocument doc,....){
PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
...
acroForm.flatten();
}
public void setPreLastPage( PDDocument doc, PDDocument activeDocument....){
activeDocument = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
PDDocumentCatalog docCatalog = activeDocument.getDocumentCatalog();
PDPage p1 = docCatalog.getPages().get(0);
PDAcroForm acroForm = docCatalog.getAcroForm();
...
acroForm.flatten();
PDPageContentStream cs = new PDPageContentStream(activeDocument, p1,PDPageContentStream.AppendMode.APPEND, true);
cs.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
activeDocument.save(out);
doc.addPage(p1);
}
public void setLastPage( PDDocument doc, PDDocument activeDocument....){
activeDocument = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
PDDocumentCatalog docCatalog = activeDocument.getDocumentCatalog();
PDPage p1 = docCatalog.getPages().get(0);
PDAcroForm acroForm = docCatalog.getAcroForm();
...
acroForm.flatten();
PDPageContentStream cs = new PDPageContentStream(activeDocument, p1,PDPageContentStream.AppendMode.APPEND, true);
cs.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
activeDocument.save(out);
doc.addPage(p1);
}
public void addExtraPage( PDDocument doc, PDDocument activeDocument....){
activeDocument = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
PDDocumentCatalog docCatalog = activeDocument.getDocumentCatalog();
PDPage p1 = docCatalog.getPages().get(0);
PDAcroForm acroForm = docCatalog.getAcroForm();
...
acroForm.flatten();
PDPageContentStream cs = new PDPageContentStream(activeDocument, p1,PDPageContentStream.AppendMode.APPEND, true);
cs.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
activeDocument.save(out);
doc.addPage(p1);
}
这些函数中有更多的逻辑,但我尝试只添加我认为相关的内容。
我认为问题与其中一个 pdf 的内容流或我关闭、保存等的顺序有关....但我无法弄清楚确切的问题是什么,所以任何建议都会不胜感激。
三个错误在 setPreLastPage
、setLastPage
和 addExtraPage
中:在这些方法中的每一个中,您在各自的局部变量 [=14] 中加载一个新的 PDDocument
=],从中取出一个页面并将其添加到相同的 PDDocument doc
,然后在离开相应方法时删除 activeDocument
中对该 PDDocument
的所有引用。
删除所有引用允许垃圾回收选择这些 PDDocument
实例并关闭并删除它们。这会拉走复制到 PDDocument doc
的页面下方的数据,导致您在尝试保存 doc
.
为防止这种情况,要么在添加页面对象之前将页面对象克隆到 doc
中,要么在保存 doc
.
如果有人对解决方案的实际实施感到好奇,我创建了一个空列表。
List<PDDocument> activeDocuments = new ArrayList<PDDocument>();
然后每次我调用其中一种方法时,我都会返回文档并将其存储在列表中,然后在保存原始文档后最后将它们全部关闭。
while (currentIndex < transactionList.size()) {
Boolean fourOrFive = false;
Boolean checkpoint = false;
Boolean finalPrint = false;
if (count == 4) {
checkpoint = statementsUtils.reachedCheckpoint(currentIndex, transactionList);
if (checkpoint) {
cutOff = currentIndex;
fourOrFive = true;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
activeDocuments.add(statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
count = 0;
}
} else if (count == 5) {
cutOff = currentIndex;
fourOrFive = false;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
activeDocuments.add(statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
count = 0;
} else if (transactionList.size() <= 2) {
finalPrint = true;
} else if (transactionList.size() - currentIndex + 1 <= 5) { // count <4? print last page or count >=4 print 4 and check homuch left
finalPrint = true;
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
if (transactionList.size() - currentIndex + 1 == 5) {
activeDocuments.add(statementsUtils.setPreLastPage(doc, activeDocument, currentIndex, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
pageNumber++;
pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
activeDocuments.add(statementsUtils.setLastPage(doc, activeDocument, transactionList.size() - 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
} else {
activeDocuments.add(statementsUtils.setLastPage(doc, activeDocument, currentIndex - count + 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
}
}
if (fourOrFive && !finalPrint)
currentIndex = cutOff + 1;
else if (finalPrint)
currentIndex = transactionList.size();
else
currentIndex++;
if (currentIndex >= 2) count++;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
PDPageContentStream contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true);
contentStream.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
if (doc != null) {
doc.save(out);
doc.close();
}
for (PDDocument a : activeDocuments)
a.close();
if (activeDocument != null) {
activeDocument.close();
}
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
return in;
}