我试图通过文件上传合并来自JSP页面的两个PDF文档。我正在获取文件,将它们放入列表中,但当我试图读取它们以进行合并时,我收到了一条“流已关闭”的消息。我搜索了很多关于这个例外的回复,但没有一个有帮助。所以,再说一遍,不确定它在哪里失败。
以下是Java代码:
public class MergePdfUtility {
FormDataBean formData = null;
public String mergePdf(String contentType, InputStream inputStream, int formDataLength,
HttpServletRequest request) {
String saveFile = new String();
String strUploadFile = "";
File flUploadFile = null;
formData = new FormDataBean();
try {
List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
List<InputStream> list = new ArrayList<InputStream>();
for (FileItem item : items) {
if (item.isFormField()) {
String fieldname = item.getFieldName();
String fieldvalue = item.getString();
if(fieldvalue == null || fieldvalue.length() == 0) {
fieldvalue = "Merger.pdf";
}
System.out.println("Field Value = " + fieldvalue);
if (fieldname.equals("txtFileName")) {
formData.setStrFileName(fieldvalue);
System.out.println("successfully assigned");
}
} else {
saveFile = FilenameUtils.getName(item.getName());
if (saveFile.endsWith(".pdf")) {
inputStream = item.getInputStream();
contentType = item.getContentType();
strUploadFile = "D:\\Samik\\BCP\\" + saveFile;
flUploadFile = new File(strUploadFile);
FileOutputStream fileout = new FileOutputStream(flUploadFile);
BufferedOutputStream bout = new BufferedOutputStream(fileout);
BufferedInputStream bin = new BufferedInputStream(inputStream);
int byte_;
while ((byte_ = bin.read()) != -1) {
bout.write(byte_);
}
list.add(inputStream);
bout.close();
bin.close();
fileout.flush();
fileout.close();
}
}
}
mergePdf(list);
} catch (Exception e) {
e.printStackTrace();
return "failure";
}
return "success";
}
private static void mergePdf(List<InputStream> list)
throws DocumentException, IOException {
OutputStream mergeOutputStream = new FileOutputStream(new File("D:\\Samik\\BCP\\" + "Merger.pdf"));
Document document = new Document();
PdfWriter pdfWriter = PdfWriter.getInstance(document, mergeOutputStream);
document.open();
PdfContentByte pdfContentByte = pdfWriter.getDirectContent();
for (InputStream tempInputStream : list) {
PdfReader pdfReader = new PdfReader(tempInputStream);
for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
document.newPage();
PdfImportedPage page = pdfWriter.getImportedPage(pdfReader, i);
pdfContentByte.addTemplate(page, 0, 0);
}
}
mergeOutputStream.close();
document.close();
}
}
我在线路上遇到了一个例外:
PdfReader pdfReader = new PdfReader(tempInputStream);
例外情况:
java.io.IOException: Stream Closed
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(Unknown Source)
at com.itextpdf.text.pdf.RandomAccessFileOrArray.InputStreamToArray(RandomAccessFileOrArray.java:179)
at com.itextpdf.text.pdf.RandomAccessFileOrArray.<init>(RandomAccessFileOrArray.java:172)
at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:237)
at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:248)
at com.tcs.pdfutil.MergePdfUtility.mergePdf(MergePdfUtility.java:108)
at com.tcs.pdfutil.MergePdfUtility.mergePdf(MergePdfUtility.java:86)
at org.apache.jsp.MergePdfUtility_jsp._jspService(MergePdfUtility_jsp.java:83)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
确切的问题是什么?正在关闭的inputStream在哪里?
===============================================================================7月3日添加:
感谢@匿名。这帮助我解决了这个问题,但部分。我现在可以合并多达5个pdf文档,甚至在合并它们后删除源文档-但我仍然无法获得成功消息。在完美地完成所有操作后,控件转到IOException,我终于得到了相同的错误-java.io.IOException: Stream Cloked
,这会导致返回“失败”消息。无法追踪出我哪里出错了。
我的代码现在如下所示:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
public class MergePdfUtility {
FormDataBean formData = null;
public String mergePdf(String contentType, int formDataLength, HttpServletRequest request) {
String saveFile = new String();
String strUploadFile = "";
File flUploadFile = null;
formData = new FormDataBean();
FileOutputStream fileout = null;
BufferedOutputStream bout = null;
BufferedInputStream bin = null;
String strStatusMsg;
InputStream inputStream1 = null;
InputStream inputStream2 = null;
InputStream inputStream3 = null;
InputStream inputStream4 = null;
InputStream inputStream5 = null;
try {
List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
List<InputStream> list = new ArrayList<InputStream>();
//List<InputStream> finalList = new ArrayList<InputStream>();
for (FileItem item : items) {
if (item.isFormField()) {
String fieldname = item.getFieldName();
String fieldvalue = item.getString() + ".pdf";
if (fieldvalue == null || fieldvalue.length() == 0 || fieldvalue.equals(".pdf")) {
fieldvalue = "Merger.pdf";
}
System.out.println("Field Value = " + fieldvalue);
if (fieldname.equals("txtFileName")) {
formData.setStrFileName(fieldvalue);
System.out.println("successfully assigned");
}
} else {
saveFile = FilenameUtils.getName(item.getName());
if (saveFile.endsWith(".pdf")) {
String strFieldName = item.getFieldName();
System.out.println(saveFile);
contentType = item.getContentType();
strUploadFile = "D:\\Samik\\BCP\\" + saveFile;
flUploadFile = new File(strUploadFile);
fileout = new FileOutputStream(flUploadFile);
bin = new BufferedInputStream(item.getInputStream());
bout = new BufferedOutputStream(fileout);
int byte_;
while ((byte_ = bin.read()) != -1) {
bout.write(byte_);
}
bout.flush();
bout.close();
//bin.close();
if(strFieldName.endsWith("1")) {
inputStream1 = new FileInputStream(flUploadFile);
list.add(inputStream1);
formData.setFile1(flUploadFile);
} else if(strFieldName.endsWith("2")) {
inputStream2 = new FileInputStream(flUploadFile);
list.add(inputStream2);
formData.setFile2(flUploadFile);
}
else if(strFieldName.endsWith("3")) {
inputStream3 = new FileInputStream(flUploadFile);
list.add(inputStream3);
formData.setFile3(flUploadFile);
}
else if(strFieldName.endsWith("4")) {
inputStream4 = new FileInputStream(flUploadFile);
list.add(inputStream4);
formData.setFile4(flUploadFile);
}
else if(strFieldName.endsWith("5")) {
inputStream5 = new FileInputStream(flUploadFile);
list.add(inputStream5);
formData.setFile5(flUploadFile);
}
}
}
}
mergePdf(list, formData);
System.out.println("Finishing the main method");
if(flUploadFile != null) {
flUploadFile.delete();
}
strStatusMsg = "success";
} catch (Exception e) {
e.printStackTrace();
strStatusMsg = "failure";
}
return strStatusMsg;
}
private static void mergePdf(List<InputStream> list, FormDataBean formData) {
OutputStream mergeOutputStream = null;
Document document = null;
try {
mergeOutputStream = new FileOutputStream(new File("D:\\Samik\\BCP\\" + formData.getStrFileName()));
document = new Document();
PdfWriter pdfWriter = PdfWriter.getInstance(document, mergeOutputStream);
document.open();
PdfContentByte pdfContentByte = pdfWriter.getDirectContent();
for (InputStream tempInputStream : list) {
PdfReader pdfReader = new PdfReader(tempInputStream);
for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
document.newPage();
PdfImportedPage page = pdfWriter.getImportedPage(pdfReader, i);
pdfContentByte.addTemplate(page, 0, 0);
}
tempInputStream.close();
pdfReader.close();
}
System.out.println("Merging completed");
deleteFiles(formData);
pdfWriter.flush();
pdfWriter.close();
} catch (DocumentException | IOException e) {
try {
throw e;
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} finally {
try {
if (mergeOutputStream != null) {
mergeOutputStream.close();
}
if (document != null) {
document.close();
}
System.out.println("Exiting the method");
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
private static void deleteFiles(FormDataBean formData) throws IOException, FileNotFoundException {
if(formData.getFile1()!=null) {
formData.getFile1().delete();
}
if(formData.getFile2()!=null) {
formData.getFile2().delete();
}
if(formData.getFile3()!=null) {
formData.getFile3().delete();
}
if(formData.getFile4()!=null) {
formData.getFile4().delete();
}
if(formData.getFile5()!=null) {
formData.getFile5().delete();
}
}
}
根据我的理解,InputStream
在传递到
mergePdf()
之前已经关闭,当
BufferedInputStream
关闭时,如下所示。
BufferedInputStream bin = new BufferedInputStream(inputStream);
...
list.add(inputStream);
...
bin.close();
您可以检查java的代码。io。BufferedInputStream#close
public void close() throws IOException {
byte[] buffer;
while ( (buffer = buf) != null) {
if (bufUpdater.compareAndSet(this, buffer, null)) {
InputStream input = in;
in = null;
if (input != null)
input.close();
return;
}
// Else retry in case a new buf was CASed in fill()
}
}
PS:我建议您关闭finally block中的IO流或使用try with resources。例如:
private static void mergePdf(List<InputStream> list) {
OutputStream mergeOutputStream = null;
Document document = null;
try{
mergeOutputStream = new FileOutputStream(new File("D:\\Samik\\BCP\\" + "Merger.pdf"));
document = new Document();
PdfWriter pdfWriter = PdfWriter.getInstance(document, mergeOutputStream);
document.open();
PdfContentByte pdfContentByte = pdfWriter.getDirectContent();
for (InputStream tempInputStream : list) {
PdfReader pdfReader = new PdfReader(tempInputStream);
for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
document.newPage();
PdfImportedPage page = pdfWriter.getImportedPage(pdfReader, i);
pdfContentByte.addTemplate(page, 0, 0);
}
}
} catch (DocumentException|IOException e) {
throw e;
} finally {
try {
if(mergeOutputStream != null) {
mergeOutputStream.close();
}
if(document != null) {
document.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
或者(确保文档已实现java.io.Closeable):
private static void mergePdf(List<InputStream> list) throws DocumentException, IOException {
try(OutputStream mergeOutputStream = new FileOutputStream(new File("D:\\Samik\\BCP\\" + "Merger.pdf")); Document document = new Document()){
PdfWriter pdfWriter = PdfWriter.getInstance(document, mergeOutputStream);
document.open();
PdfContentByte pdfContentByte = pdfWriter.getDirectContent();
for (InputStream tempInputStream : list) {
PdfReader pdfReader = new PdfReader(tempInputStream);
for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
document.newPage();
PdfImportedPage page = pdfWriter.getImportedPage(pdfReader, i);
pdfContentByte.addTemplate(page, 0, 0);
}
}
}
}
2018年7月4日更新。试验方法符合https://developers.itextpdf.com/question/how-merge-documents-correctly.
public static void mergePdf(List<InputStream> inputStreams, String destinationFile) {
try (OutputStream mergeOutputStream = new FileOutputStream(new File(destinationFile))) {
Document document = new Document();
PdfCopy copy = new PdfSmartCopy(document, mergeOutputStream);
document.open();
for (InputStream tempInputStream : inputStreams) {
PdfReader pdfReader = new PdfReader(tempInputStream);
copy.addDocument(pdfReader);
System.out.println("Merging completed");
pdfReader.close();
tempInputStream.close();
}
document.close();
copy.close();
} catch (DocumentException | IOException e) {
e.printStackTrace();
}
}
更新于2018年7月5日,我不知道你在使用什么框架。但是我已经成功地将两个pdf与Springboot2.0.1合并。释放。这是我的测试代码
@ResponseBody
@RequestMapping(value = "/mergePdf.json", method = POST)
public void mergePdf(@RequestParam("files") MultipartFile[] files) {
mergePdfViaIText(Arrays.stream(files).map(file -> {
try {
LOG.debug(file.getOriginalFilename());
return file.getInputStream();
} catch (IOException e) {
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList()), "D:/result.pdf");
}
public static void mergePdfViaIText(List<InputStream> inputStreams, String destinationPath) {
try (OutputStream mergeOutputStream = new FileOutputStream(new File(destinationPath))) {
Document document = new Document();
PdfCopy copy = new PdfSmartCopy(document, mergeOutputStream);
document.open();
for (InputStream tempInputStream : inputStreams) {
PdfReader pdfReader = new PdfReader(tempInputStream);
copy.addDocument(pdfReader);
LOG.info("Merging completed");
pdfReader.close();
tempInputStream.close();
}
document.close();
copy.close();
} catch (DocumentException | IOException e) {
LOG.error(e.getMessage(), e);
}
}
你能告诉我,我的代码出了什么问题吗?我用它来合并PDF,我创建一个内存流,然后将其输出到PDF。它对我来说很好,但一些用户无法在IE中下载文件,或者在Chrome中出现网络错误: 调试后,我注意到内存流msOutput有一些错误: 是什么导致了它,以及如何避免它? 谢谢你。
我试图把我单独的Java文件在1类。它看起来像这样。 但是我遇到了一个错误 "异常在线程"main"java.lang.错误:未解决的编译问题:没有封闭的实例类型oneClass是可访问的。必须用问题2类型的封闭实例来限定分配(例如x.newA()其中x是问题2的实例)。 发生什么事?
问题内容: 这是我目前拥有的代码: 一切都会按预期进行(调用writeToFile方法时将文件写入)。但是,当第二次调用writeToFile方法时,出现以下错误: 该文件仍按预期第二次写入,但是它将在第二次以及以后对writeToFile()的调用中引发此错误。我想知道是什么导致此错误发生。 问题答案: 写完后就在打电话。流关闭后,将无法再次写入。通常,实现此目标的方法是将结束状态移至write
我想将至少2个PDF文件合并为一个,同时保留原始PDF中的所有表单元素。表单元素包括文本字段、单选按钮、复选框、下拉菜单等。请查看此示例PDF文件的表单: 你能做到吗? 编辑:至于实现,我更希望在linux平台上使用开源工具(如'ghostscript'或任何其他您认为适合解决此任务的工具)的命令行解决方案。 当然,欢迎每个人提供解决这个问题的任何工作解决方案,包括一个编码解决方案,它涉及编写一个
问题内容: 我有一个程序需要合并两个。哈希图的键为a ,值为。合并的特殊条件是,如果键已在字典中,则需要将其添加到现有值中而不是替换它。这是我到目前为止抛出的代码。 问题答案: 如果您的代码不能保证会在到达此方法之前将其初始化,则您将必须执行null检查,没有出路 考虑到HashMap允许将null作为值在代码中容易发生NPE的另一个位置是 如果这两个都不为空,则将获得NPE。
我正在将一些旧的iTextSharp代码升级到新的iText 7库。我很难确定将2个PDF MemoryStream合并为一个PDF MemoryStream的正确方法,该PDF MemoryStream包含来自两个源PDF MemoryStream的所有页面。这看起来很简单,我认为下面的代码设置正确,但生成的PDF内存流只包含第一个文件。第二个PDF文件从未出现,也从未连接到第一个PDF文件。