ColdFusion 8 より追加されている<cfzip>タグは、標準の java.util.zip が使われていますが、このライブラリはパスワード付きZIPファイルの操作を行うことができないことと、ファイル名に日本語が含まれている場合に、文字コードをUTF-8で固定して処理を行います。そのため、<cfzip>タグを使ってファイルの圧縮や解凍などを行うと、Windows環境では文字化けを起こす結果となります。標準のライブラリでは行えない処理に対して、Zip4Jを使った例を紹介します。
ColdFusion 実験室で公開している情報は、ColdFusionの標準の機能では無いため動作の保証外(未サポート)となります。下記の事項も含めてそれらを予めご認識頂いた上で、参考にされるかどうかをご判断下さい。
  Zip4jConstants.java と ZipParameters.java の設定項目とメソッドを確認
http://grepcode.com/file/repo1.maven.org/maven2/net.lingala.zip4j/zip4j/1.3.1/net/lingala/zip4j/util/Zip4jConstants.java
http://grepcode.com/file/repo1.maven.org/maven2/net.lingala.zip4j/zip4j/1.3.1/net/lingala/zip4j/model/ZipParameters.java
このサンプルでは、Zip4JライブラリからZipFile、Zip4jConstants、ZipParametersクラスのインスタンスを作成して、所定のメソッドを実行してzipファイルを作成しています。初期値として、SourceDir(圧縮するフォルダ)、zipFileName(zipファイルの保存先)、zipPassword(パスワード)を指定して下さい。パスワードに値が指定されている場合はパスワードをセットするメソッドも実行します。また、圧縮するファイルに日本語のファイル名が含まれている場合は、ファイル名に対するエンコードを setFileNameCharsetメソッドで指定して、Windows-31J(日本語Shift_JIS)を指定することで Windows環境でファイルの文字化けを防ぐことができます。
<cfscript>
//圧縮するフォルダを指定
SourceDir="c:\temp";
//圧縮したZIPファイルの置き場所を指定
zipFileName=ExpandPath('./out/zippedFiles.zip');
//ZIPファイルにパスワードを掛ける場合はパスワードを指定(指定しない場合は"")
zipPassword="test123";
zipFile = createObject("java", "net.lingala.zip4j.core.ZipFile").init(zipFileName);
zipFile.setFileNameCharset("Windows-31J");
zipConstants = createObject("java", "net.lingala.zip4j.util.Zip4jConstants");
zipParameters = createObject("java", "net.lingala.zip4j.model.ZipParameters");
//圧縮率
zipParameters.setCompressionMethod(zipConstants.COMP_DEFLATE);
zipParameters.setCompressionLevel(zipConstants.DEFLATE_LEVEL_NORMAL);
//パスワードが空白でない場合は、パスワードをセットする
if(zipPassword IS NOT ""){
	zipParameters.setEncryptFiles(true);
	zipParameters.setEncryptionMethod(zipConstants.ENC_METHOD_STANDARD);
	zipParameters.setPassword(zipPassword);
}
//圧縮の実行
zipFile.addFolder(SourceDir, zipParameters);
</cfscript>
各クラスにどのようなメソッドがあるかを参照したい場合は、上記の参照サイト(grepcode.com)の内容を参考にするか、または<cfdump>やWriteDump()でオブジェクトを指定して確認下さい。
例:<cfdump var="#zipFile#">
    
このサンプルでは、ZIPファイル内のファイルリストを表示します。対象のZIPファイルのパス・ファイル名を変数にセットし、その値を使ってZipFileのインスタンスを作成します。getFileHeaders()メソッドの結果はColdFusion配列に格納されますので、その後は配列に対するループを行い、getFileName()メソッドでファイル名を取得して表示します。
<cfscript>
//対象のZIPファイルのファイル・パスを指定
zipFilePath = ExpandPath('./out/zippedFiles.zip');
zipFile = createObject('java', 'net.lingala.zip4j.core.ZipFile').init(zipFilePath); 
zipFile.setFileNameCharset("Windows-31J");
//ファイルヘッダを取得する(ファイル一覧は配列データ)
aFileHeaders=zipFile.getFileHeaders();
//配列をループし、ファイル名を表示する
for(i=1; i LTE ArrayLen(aFileHeaders); i=i+1) {
	if(not aFileHeaders[i].isDirectory()){
	    writeOutput(aFileHeaders[i].getFileName() & "<br>");
	}
}
</cfscript>
このサンプルでは、該当するZIPファイルを解凍します。ZipFileライブラリのisEncrypted()メソッドで、ZIPファイルにパスワードが掛かっている場合は、setPassword()でパスワードを指定しています。誤ったパスワードを指定していると、解凍時(exactAll()メソッド実行時)にエラーが発生するため、サンプルには例外処理を含めています。
<cfscript>
//対象のZIPファイルのファイル・パスを指定
zipFilePath = ExpandPath('./out/zippedFiles.zip');
//解凍先のフォルダを指定
destPath = ExpandPath('./out/');
//ZIPファイルの解除用パスワードを指定(パスワードが掛かっていない場合は"")
zipPassword = "test123";
zipFile = createObject('java', 'net.lingala.zip4j.core.ZipFile').init(zipFilePath); 
zipFile.setFileNameCharset("Windows-31J");
if(zipFile.isEncrypted()){
	zipFile.setPassword(zipPassword);
}
try {
	zipFile.extractAll(destPath);
}
catch(any excpt) {
	writeOutput("ファイルの解凍に失敗しました。パスワードが間違っているかもしれません。<br>");
	writeOutput("エラーメッセージ:" & excpt.message);
}
</cfscript>
今回の実験室はいかがだったでしょうか?上記では該当する処理の部分のみを紹介していますが、処理をUDFやCFCにまとめて色々なページから呼び出すなども効果的かと思います。
ColdFusionはJavaをベースとしたアプリケーションのため、JavaライブラリとColdFusionとの組み合わせが可能なものであれば、既存の機能で足りない部分を補う効果が期待できます。
ただし、Javaライブラリとの組み合わせで動かせる範囲に制限があったり、そもそもまともに動かなかったりするものもあると思います。主に海外の情報となりますがColdFusionとJavaライブラリを組み合わせた色々な情報が掲載されていますので、それらの情報もぜひ参考にして下さい。

