如何在Java Swing中打开/查看.doc/.pdf及数据库存储的对应文件?
我来帮你搞定这两个Java Swing里处理文档的问题,都是开发中常碰到的场景,咱们一步步拆解:
一、在Java Swing应用中打开/查看本地的.doc/.pdf文件
处理PDF文件
有两种常见方式:内嵌到Swing界面查看或者调用系统默认程序打开。
1. 内嵌查看(推荐用Apache PDFBox)
PDFBox是Apache的开源库,能直接把PDF页面渲染成图片,放到Swing组件里展示。
首先你需要引入依赖(Maven为例):
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.32</version> </dependency>
然后写个简单的示例代码,把PDF渲染到JScrollPane里:
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.PDFRenderer; import javax.swing.*; import java.awt.*; import java.io.File; public class PdfViewer extends JFrame { public PdfViewer(File pdfFile) { setTitle("PDF Viewer"); setSize(800, 600); setDefaultCloseOperation(DISPOSE_ON_CLOSE); try (PDDocument document = PDDocument.load(pdfFile)) { PDFRenderer renderer = new PDFRenderer(document); JPanel panel = new JPanel(new GridLayout(document.getNumberOfPages(), 1)); for (int i = 0; i < document.getNumberOfPages(); i++) { Image image = renderer.renderImageWithDPI(i, 96); // 96DPI和屏幕匹配 panel.add(new JLabel(new ImageIcon(image))); } add(new JScrollPane(panel)); } catch (Exception e) { JOptionPane.showMessageDialog(this, "加载PDF失败:" + e.getMessage()); e.printStackTrace(); } } public static void main(String[] args) { SwingUtilities.invokeLater(() -> new PdfViewer(new File("your-file.pdf")).setVisible(true)); } }
2. 调用系统默认程序打开
如果不需要内嵌,直接让系统自带的PDF阅读器打开更简单,用Java的Desktop类:
import java.awt.Desktop; import java.io.File; public class OpenPdfWithSystem { public static void openPdf(File pdfFile) { if (Desktop.isDesktopSupported()) { try { Desktop.getDesktop().open(pdfFile); } catch (Exception e) { e.printStackTrace(); } } } }
处理.doc文件
Java没有原生支持doc格式,得借助第三方库,或者直接调用系统程序:
1. 读取文本内容并内嵌展示(用Apache POI HWPF)
HWPF是POI专门处理旧版.doc文件的组件,能读取文本内容(格式可能会丢失,要保留复杂格式的话比较麻烦)。
先引入依赖:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>5.2.3</version> </dependency>
然后写代码读取并显示在JTextPane里:
import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.extractor.WordExtractor; import javax.swing.*; import java.io.File; public class DocViewer extends JFrame { public DocViewer(File docFile) { setTitle("DOC Viewer"); setSize(800, 600); setDefaultCloseOperation(DISPOSE_ON_CLOSE); JTextPane textPane = new JTextPane(); textPane.setEditable(false); add(new JScrollPane(textPane)); try (HWPFDocument document = new HWPFDocument(docFile.toPath())) { WordExtractor extractor = new WordExtractor(document); textPane.setText(extractor.getText()); } catch (Exception e) { JOptionPane.showMessageDialog(this, "加载DOC失败:" + e.getMessage()); e.printStackTrace(); } } public static void main(String[] args) { SwingUtilities.invokeLater(() -> new DocViewer(new File("your-file.doc")).setVisible(true)); } }
2. 调用系统默认程序打开
和PDF一样,用Desktop类直接打开,简单省心:
import java.awt.Desktop; import java.io.File; public class OpenDocWithSystem { public static void openDoc(File docFile) { if (Desktop.isDesktopSupported()) { try { Desktop.getDesktop().open(docFile); } catch (Exception e) { e.printStackTrace(); } } } }
二、打开/查看存储在数据库(longblob)中的.pdf/.doc文件
核心思路是:把数据库里的二进制Blob数据导出到临时文件,然后就可以用上面本地文件的处理方法来查看了。毕竟大多数文档处理库都是基于文件路径或输入流工作的,临时文件是最通用的方案。
步骤1:从数据库读取Blob数据并写入临时文件
假设你的FileAttachment类有getFileData()方法返回Blob对象(或者直接返回InputStream),Dao层的方法大概是这样:
import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.sql.Blob; public class FileDao { // 假设这是你从数据库获取FileAttachment的方法 public FileAttachment getFileAttachmentById(long id) { // 这里写你的JDBC/JPA查询逻辑,返回FileAttachment对象 return null; } // 把Blob转成临时文件 public File blobToTempFile(Blob blob, String fileExtension) throws Exception { // 创建临时文件,比如temp-xxxx.pdf File tempFile = File.createTempFile("temp-", "." + fileExtension); tempFile.deleteOnExit(); // 程序退出时自动删除临时文件 try (InputStream is = blob.getBinaryStream(); FileOutputStream fos = new FileOutputStream(tempFile)) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { fos.write(buffer, 0, bytesRead); } } return tempFile; } }
步骤2:用临时文件打开文档
拿到临时文件后,就可以复用上面本地文件的代码了,比如查看PDF:
public class DbDocumentViewer { public static void viewPdfFromDb(long fileId) { FileDao dao = new FileDao(); FileAttachment attachment = dao.getFileAttachmentById(fileId); try { File tempPdf = dao.blobToTempFile(attachment.getFileData(), "pdf"); // 用之前的内嵌查看方法 SwingUtilities.invokeLater(() -> new PdfViewer(tempPdf).setVisible(true)); // 或者调用系统程序:OpenPdfWithSystem.openPdf(tempPdf); } catch (Exception e) { JOptionPane.showMessageDialog(null, "加载数据库中的PDF失败:" + e.getMessage()); e.printStackTrace(); } } public static void viewDocFromDb(long fileId) { FileDao dao = new FileDao(); FileAttachment attachment = dao.getFileAttachmentById(fileId); try { File tempDoc = dao.blobToTempFile(attachment.getFileData(), "doc"); // 用内嵌查看方法 SwingUtilities.invokeLater(() -> new DocViewer(tempDoc).setVisible(true)); // 或者调用系统程序:OpenDocWithSystem.openDoc(tempDoc); } catch (Exception e) { JOptionPane.showMessageDialog(null, "加载数据库中的DOC失败:" + e.getMessage()); e.printStackTrace(); } } }
注意点
- 临时文件记得设置
deleteOnExit(),避免磁盘占用过多;也可以在关闭查看窗口时手动删除。 - 如果你的
FileAttachment类存储的是byte[]而不是Blob,那直接把byte[]写入临时文件就行,逻辑更简单。 - 大文件的话,建议用流的方式逐步写入,不要一次性加载到内存里,避免OOM。
内容的提问来源于stack exchange,提问作者Anirudh Lou
相关产品推荐
相关产品推荐

