Java 広告

【Java】Javaでパスワード付ZIPファイルを作成する方法

記事内に商品プロモーションを含む場合があります

今回はJavaでパスワード付ZIPファイルを作成する方法を紹介します。

以前、パスワードが無いZIPファイルを作成する方法を紹介しましたが、こちらは標準のライブラリを使用しており、標準ライブラリにパスワード付ZIPを生成するために必要な機能が含まれていませんでした。

そこで、今回はパスワード付ZIPを生成するために、外部ライブラリを使用して、パスワード付きのZIPファイルを作成する方法を紹介します。

パスワード付ZIPファイルを外部ライブラリを使わずに実装することも可能ですが、かなり難しい知識が必要になってくるので、外部ライブラリを用いたほうが現実的な選択になるかと思います。

必要なライブラリ

今回、パスワード付ZIPファイルを生成するために一つ、外部ライブラリを使用します。

それはzip4jというライブラリです。

このライブラリを使うことで、比較的簡単にパスワード付きZIPファイルを作成することが出来ます。

こちらのGitHubに詳しい使い方の説明が書かれていますが、英語で記載されているため、なかなか理解しにくい点があるかと思いますので、本記事で実際に組んだソースを例に挙げながら説明していきたいと思います。

なお、このライブラリの更新は2年前で止まっていますが、2025年時点でも普通に使えるため、今はこうすれば実装できるというのを理解して頂ければと思います。

いつか使えなくなる可能性があるうえ、このライブラリはApache License2.0に従うため、再配布や商用利用に関しては制限事項があります。

ただし、個人での学習にはそこまで気にする必要はないため、個人利用の為であれば気にせず使っていただいて構いません。

パスワード付ZIPの実装方法

今回はSpring Bootを使って実装をしてみたいと思います。

まず初めに、EclipseでSpring Bootのプロジェクトを作成します。

この時に必要であればThymeLeafを使うように設定しておいてください。

次に、作成したプロジェクトのbuild.gradleを開きます。

dependenciesに以下の1行を追加します。

implementation 'net.lingala.zip4j:zip4j:2.11.5'


こうすることで、zip4jで用意されている関数を使うことが出来るようになります。


次に、Javaでの実装ですが、以下のような形で書くと良いでしょう。

package com.example.demo;


import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;


@Controller
@RequestMapping()
public class sampleController {
	@PostMapping("/do/CreateZipEncrypted")
	private static String CreateZipEncrypted(Frm form, Model model) throws Exception{

		//出力Zipファイル名、フォルダパス
		String zipPath = "test.zip";
		
		//パスワードを定義
		String password ="12345E";
		//出力するzipファイルのパスを設定
		ZipFile zipFile = new ZipFile(zipPath, password.toCharArray());
		
		//圧縮対象ファイル
		List<File> sources = new ArrayList<>();
		sources.add(new File("test.csv"));

		//暗号化Zipファイルを作成するためのパラメータ
		ZipParameters params = new ZipParameters();
		params.setCompressionMethod(CompressionMethod.DEFLATE);
		params.setCompressionLevel(CompressionLevel.NORMAL);
		
		//暗号化を行う(標準zip形式)
		params.setEncryptFiles(true);
		params.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);
		
		//ファイル、ディレクトリを追加していく
		for (File f : sources) {
			if (!f.exists()) {
				//ファイルが存在しなかったら何もしない
				continue;
			}
			if (f.isDirectory()) {
				zipFile.addFolder(f, params);
			} else {
				zipFile.addFile(f, params);
			}
		}
		
		zipFile.close();
		
		return "sample";
	}
	@GetMapping("/index")
	public String index(Model model) {
		return "sample";
	}
}

上記のソースの中で、

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;

の部分が、パスワード付ZIPファイルを作成するのに必要なzip4jのライブラリをインポートする処理になります。

そして、

	private static String CreateZipEncrypted(Frm form, Model model) throws Exception{

		//出力Zipファイル名、フォルダパス
		String zipPath = "test.zip";
		
		//パスワードを定義
		String password ="12345E";
		//出力するzipファイルのパスを設定
		ZipFile zipFile = new ZipFile(zipPath, password.toCharArray());
		
		//圧縮対象ファイル
		List<File> sources = new ArrayList<>();
		sources.add(new File("test.csv"));

		//暗号化ZIPファイルを作成するためのパラメータ
		ZipParameters params = new ZipParameters();
		params.setCompressionMethod(CompressionMethod.DEFLATE);
		params.setCompressionLevel(CompressionLevel.NORMAL);
		
		//暗号化を行う(標準zip形式)
		params.setEncryptFiles(true);
		params.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);
		
		//ファイル、ディレクトリを追加していく
		for (File f : sources) {
			if (!f.exists()) {
				//ファイルが存在しなかったら何もしない
				continue;
			}
			if (f.isDirectory()) {
				zipFile.addFolder(f, params);
			} else {
				zipFile.addFile(f, params);
			}
		}
		
		zipFile.close();
		
		return "sample";
	}

の部分が、パスワード付ZIPファイルを出力する処理となっています。

上記の処理では、以下の順番で処理を行っています。

  1. 3~4行目:出力ファイルパスを指定(ソースではプロジェクトフォルダの直下に作成)
  2. 6~9行目:パスワード付ZIPファイルを定義(パスワードはChar型の配列であり、Stringが使えないことに注意)
  3. 11~13行目:ZIPファイルに含めるファイルを定義(このプログラムではファイルのみですが、フォルダを含むことも出来ます)
  4. 15~18行目:ファイルの圧縮方法、圧縮レベルの設定(この通りに書いた方が無難です)
  5. 20~22行目:暗号化のための設定(特にこだわりが無ければこの書き方でいいと思います)
  6. 24~37行目:ZIPファイルに圧縮対象のファイルやフォルダを追加していく処理。最後はZIPファイルに対してClose処理を入れています。

では、以下のようにボタンだけを置いたHTMLファイルを表示用に作成して、動作を試してみることにします。

<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>暗号化ZIP作成</title>
 </head>
  <body>
  <form action="#" th:action="@{/do/CreateZipEncrypted}" method="post">
      <input type="submit" value="暗号化ZIP作成">
  </form>
  </body>
</html>

ボタンを押すと、プロジェクトフォルダの直下にZIPファイルが作成されました。

このZIPを解凍しようとすると、以下のようにパスワードを入力するダイアログが表示されます。

パスワードに、ソース上で定義した「12345E」のパスワードを入力すると、無事に解凍が出来ることが確認できました。

zip4jを使ってパスワード付ZIPファイルを作成するときの注意点

最後に、zip4jを使ってパスワード付ZIPファイルを作成する場合の注意点をお話しして終わりたいと思います。

まず、zip4jは先ほどお話しした通りApache License2.0のライセンスに従うため、Apache License2.0のライセンス規約に違反しないように注意しなければいけません。

特に商用利用時や、このライブラリを使ったアプリを二次配布しようと考える場合は、ライセンス規約に違反しないように慎重に利用する必要があるでしょう。


次に、今回のサンプルのソースでは処理をtry~catch文で囲んでいません。

そのため、存在しないファイルを圧縮しようとした場合に例外で落ちてしまいますので、なるべくtry~catchで処理を囲んで、finallyにclose()処理を入れた方が良いでしょう。


また、業務でパスワード付ZIPファイルを生成しようとする場合、パスワードをソースにべた書きするのは厳禁です。

今回はサンプルプログラムだから許されますが、パスワードはソースを見られても分からないように暗号化しておくか、データベースに格納する、ランダムで生成するなど、パスワードが流出しないように工夫が必要です。


大きな業務でパスワード付ZIPを生成したい場合はzip4jに頼るよりも独自にライブラリを作成するように考えた方がいいかもしれません。

パスワード付ZIPファイルを自力で生成するのはかなり骨が折れますが、zip4jがいつ使えなくなるかが分からないですし(GitHubが2年更新されていないのを見て特にそう思います)、自力で仕組みを作っておくと、何年も技術として残ります。

なので、安易にライブラリに頼らずに自力で作り上げるということも視野に入れて、業務システムにパスワード付ZIPの技術を取り入れる作業を行ってほしいと思います。

今回の記事はここまでとなります。
また次の記事でお会いしましょう。