如何读取PDF文件并将其写入输出流

16

我需要读取一个文件路径为 "C:\file.pdf" 的pdf文件,并将其写入outputStream。最简单的方法是什么?

@Controller
public class ExportTlocrt {

@Autowired
private PhoneBookService phoneBookSer;

private void setResponseHeaderTlocrtPDF(HttpServletResponse response) {
    response.setContentType("application/pdf");
    response.setHeader("content-disposition", "attachment; filename=Tlocrt.pdf" );
} 

@RequestMapping(value = "/exportTlocrt.html", method = RequestMethod.POST)
public void exportTlocrt(Model model, HttpServletResponse response, HttpServletRequest request){

    setResponseHeaderTlocrtPDF(response);
    File f = new File("C:\\Tlocrt.pdf");

    try {
        OutputStream os = response.getOutputStream();
        byte[] buf = new byte[8192];
        InputStream is = new FileInputStream(f);
        int c = 0;
        while ((c = is.read(buf, 0, buf.length)) > 0) {
            os.write(buf, 0, c);
            os.flush();
        }
        os.close();
        is.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

}
}

...........................................................................................


你的问题似乎是要求从文件复制到专用的“OutputStream”例程,@Pheonix的答案展示了如何实现这一点 --- 你标记问题为[pdf]更不用说[itext]了,这有什么原因吗? - mkl
我在我的项目中使用了Itext来完成其他任务,因此我认为它可能可以在这个例子中使用。但是我错了。 - Juraj Vlahović
实际上,就像@Stephan的答案提供了使用PDFBox的解决方案一样,您也可以使用iText首先解析整个PDF,然后再将其序列化。但是,使用PDF库(无论是PDFBox还是iText)复制PDF是一种巨大的资源浪费,并且可能会改变所涉及的PDF。 - mkl
使用Apache FileUtils:outputStream.write(FileUtils.readFileToByteArray(file)); - user1303718
2个回答

30
import java.io.*;


public class FileRead {


    public static void main(String[] args) throws IOException {


        File f=new File("C:\\Documents and Settings\\abc\\Desktop\\abc.pdf");

        OutputStream oos = new FileOutputStream("test.pdf");

        byte[] buf = new byte[8192];

        InputStream is = new FileInputStream(f);

        int c = 0;

        while ((c = is.read(buf, 0, buf.length)) > 0) {
            oos.write(buf, 0, c);
            oos.flush();
        }

        oos.close();
        System.out.println("stop");
        is.close();

    }

}

到目前为止,最简单的方式。希望这能帮到你。


1
你的代码可能有些东西缺失了,或者是我漏掉了什么?我得到的文件大小为0字节,无法打开。我会在问题中编辑我的代码。 - Juraj Vlahović
@JurajVlahović:完美运行。 - ATR
你能快速看一下我的代码吗?也许我漏掉了什么。 - Juraj Vlahović
我已经找到了问题所在。现在它运行得很好,我会编辑我的代码。再次感谢。 - Juraj Vlahović
也许更好的做法是将从变量 is 读取的代码放在 try-finally 块中,并将 is.close() 语句放在 finally 中,以确保读取资源永远不会被遗留打开?与 oos 变量相关联的写入资源也是如此。 - user3289695

11

你可以使用Apache的PdfBox,它简单易用且性能良好。

这是从PDF文件中提取文本的示例(你可以在这里阅读更多):

import java.io.*;
import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.util.*;

public class PDFTest {

 public static void main(String[] args){
 PDDocument pd;
 BufferedWriter wr;
 try {
         File input = new File("C:\\Invoice.pdf");  // The PDF file from where you would like to extract
         File output = new File("C:\\SampleText.txt"); // The text file where you are going to store the extracted data
         pd = PDDocument.load(input);
         System.out.println(pd.getNumberOfPages());
         System.out.println(pd.isEncrypted());
         pd.save("CopyOfInvoice.pdf"); // Creates a copy called "CopyOfInvoice.pdf"
         PDFTextStripper stripper = new PDFTextStripper();
         wr = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(output)));
         stripper.writeText(pd, wr);
         if (pd != null) {
             pd.close();
         }
        // I use close() to flush the stream.
        wr.close();
 } catch (Exception e){
         e.printStackTrace();
        } 
     }
}

更新:

您可以使用PDFTextStripper获取文本:

PDFTextStripper reader = new PDFTextStripper();
String pageText = reader.getText(pd); // PDDocument object created

Pdf 包含一些图片和少量文本。我不需要将它写入 txt 或其他文件,只需将其写入 OutputStream。 - Juraj Vlahović
这只是一个例子,你可以很容易地修改它。 - Stephan
2
使用PDF处理库来复制PDF相当浪费资源,不是吗... - mkl
1
这是一个有争议的问题... 如果将来需要对 PDF 进行一些修改和/或性能不是一个巨大的因素,我认为可以使用库,特别是由于库与主应用程序分离,更加清晰。 - Stephan
谢谢你的帮助,但我会使用上面的例子,因为它更简单,适合我需要做的事情。 - Juraj Vlahović
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接