PDFファイルのパスワードをパスワードなしの状態で保存しておく方法
Posted on 2021/8/21 at 2:30
Update on 2022/3/22 at 1:18
私の職場では2021年4月から給料明細がPDF化されてメールで送信されるようになりました。
入社してから給料明細を捨てないでとってあるので、PDFをフォルダにまとめて保存していたのですが、ファイルを開くのに毎回パスワードを入力しなくてはいけません。
パスワードを解除した状態で保存する方法について調べていたのですが、結論から言うと無料版のAdobe Acrobat Readerではできないため、Chromeの 印刷機能のうち「PDFに保存」する方法で、パスワードを解除して保存することができました。
フリーソフトなどでもパスワードを解除できそうでしたが、ダウンロードとインストール作業が面倒そうだったため、Chromeでやってみることに。 私のPCにはChromeがインストール済みだったので、この方法だとたった4ステップで完了し最も簡単でした。Chrome使用している人には手軽でおすすめです。
しかし、簡単とはいえ毎回パスワードを入力するのが面倒になってきてしまい、結局自分でプログラムを書いて使用しています。せっかく書いたのでそちらの方法についても 解説していきます。
目次
Chromeを利用してPDFのパスワードを解除する方法
JavaでPDFのパスワードを解除する方法
ライブラリの準備
Javaの標準機能だけでは実装が難しそうなので何か便利なライブラリがないかと調べてみた結果、 「PDFBox」というフリーライブラリに関する情報が多かったため、これを利用してみます。
今回はPDFのパスワードの解除と設定が目的なので、PDFBox本体とcommons-loggingだけあれば問題ないので、 以下のライブラリをダウンロードしてクラスパスに追加しておきます。2022/01/31時点での最新バージョンは以下です。
サンプルコード
JFileChooserでPDFを選択し、パスワードを入力(InputPasswordDialogクラス)して再度JFileChooserを使用してPDFを保存します。
PDFUtil.java
unlock(): パスワードを解除して別ファイルとして保存することができます。
protect(): PDFファイルにパスワードを設定し保存することができます。
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.swing.JFileChooser;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException;
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
public class PDFUtil {
public static void main(String[] args) {
new PDFUtil().unlock();
}
public void unlock() {
PDDocument doc = null;
FileInputStream is;
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
JFileChooser filechooser = new JFileChooser(".");
FileFilter filter = new FileNameExtensionFilter("PDFファイル", "pdf");
filechooser.addChoosableFileFilter(filter);
filechooser.setFileFilter(filter);
int selected = filechooser.showOpenDialog(null);
if (selected != JFileChooser.APPROVE_OPTION)
return;
File input = filechooser.getSelectedFile();
is = new FileInputStream(input);
try {
doc = Loader.loadPDF(is);
} catch (InvalidPasswordException e) {
InputPasswordDialog passDialog = new InputPasswordDialog();
String password = passDialog.showDialog(null);
is = new FileInputStream(input);
doc = Loader.loadPDF(is, password);
}
if (filechooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION)
return;
doc.setAllSecurityToBeRemoved(true);
doc.save(filechooser.getSelectedFile());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (doc != null)
doc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void protect() {
PDDocument doc = null;
FileInputStream is;
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
JFileChooser filechooser = new JFileChooser(".");
FileFilter filter = new FileNameExtensionFilter("PDFファイル", "pdf");
filechooser.addChoosableFileFilter(filter);
filechooser.setFileFilter(filter);
int selected = filechooser.showOpenDialog(null);
if (selected != JFileChooser.APPROVE_OPTION)
return;
is = new FileInputStream(filechooser.getSelectedFile());
doc = Loader.loadPDF(is);
InputPasswordDialog passDialog = new InputPasswordDialog();
String password = passDialog.showDialog(null);
AccessPermission ap = new AccessPermission();
StandardProtectionPolicy spp = new StandardProtectionPolicy("", password, ap);
spp.setEncryptionKeyLength(128);
doc.protect(spp);
filechooser.showSaveDialog(null);
doc.save(filechooser.getSelectedFile());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (doc != null)
doc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
InputPasswordDialog.java
パスワード入力用ダイアログを表示するクラス
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.FlowLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
public class InputPasswordDialog extends JDialog {
private String password;
public InputPasswordDialog() {
setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setSize(500, 120);
setTitle("パスワードの入力");
}
public String showDialog(Window parent) {
setLocationRelativeTo(parent);
JLabel label = new JLabel("パスワードを入力してください: ");
final JPasswordField passField = new JPasswordField(15);
passField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
if (passField.getPassword().length > 0) {
char[] pass = passField.getPassword();
password = new String(pass);
dispose();
}
}
}
});
Container c = getContentPane();
c.setLayout(new BorderLayout());
JPanel center = new JPanel();
center.setLayout(new FlowLayout(FlowLayout.LEADING));
center.add(label);
center.add(passField);
JPanel south = new JPanel();
south.setLayout(new FlowLayout(FlowLayout.TRAILING));
JButton ok = new JButton("O K");
ok.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
char[] pass = passField.getPassword();
password = new String(pass);
dispose();
}
});
JButton cancel = new JButton("Cancel");
cancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
password = null;
dispose();
}
});
south.add(ok);
south.add(cancel);
c.add(center, BorderLayout.CENTER);
c.add(south, BorderLayout.SOUTH);
setVisible(true);
return password;
}
}
実行結果
まずはprotect()メソッドでPDFファイルをパスワードで保護します。
パスワードを設定するファイルを選択します。
設定するパスワードを入力します。
パスワードで保護したPDFファイルの保存先とファイル名を選択します。今回は「protect.pdf」として保存しました。
保存したPDFファイルを開くとAcrobatReaderが起動し、パスワードの入力を求められます。先程設定したパスワードを入力するとファイルが開けます。
次にprotect()で保護したPDFファイルをunlock()メソッドでパスワードを解除して、そのまま保存してみます。
パスワードを解除するファイルを選択します。
パスワードを入力します。
パスワードを解除したPDFファイルの保存先とファイル名を選択します。今回は「unlock.pdf」として保存しました。
保存したPDFファイルを開くとAcrobatReaderが起動し、パスワードの入力なしでファイルが開けるようになります。
まとめ
今回は汎用性を持たせるためにFileChooserやパスワードの入力画面を用意しましたが、私は同じパスワードで保護されたPDFをまとめて解除して 保存したいため、あるフォルダに入れたPDFをまとめて処理しています。
【JAVA】PDFBoxで複数ページあるPDFを画像に変換する
複数ページあるPDF文書をフリーライブラリであるPDFBoxを使用して、画像に変換する方法を解説します。サンプルコードあり。