今は遥かに効率の良い圧縮形態が出ているけども、まだまだ現役なzip圧縮。
元からあるdllを参照に追加するだけかと思いきや、.Net Frameworkバージョンが古い場合は色々制限があって想定と違った話。
最初にやった事
今回は共有フォルダに置かれているエクセルを、ZIPで固めて添付してメールを送るシステムを作る事に。
ZIPするならZipFileクラスで行うのが一般的らしいのでまず以下を実施してみた。
プロジェクト→参照の追加で【C:\Windows\Microsoft.NET\Framework\v4.0.30319】にある、
System.IO.Compression.FileSystem.dll、System.IO.Compression.ZipFile.dllを追加する。
※最後のv4.0.30319は人によりけり
実行環境
OS:Win10 1903
IDE:Visual Studio Express 2013
MakeZip(System.IO.Compression)
フォルダパスを指定してZipするので、圧縮したいファイルと同じ階層に同じ名前のフォルダを作成し、その中にファイルをコピーさせてみた。すっごい回りくどいけどテスト段階だったからご愛敬と言う事で・・・
using System.IO.Compression;
private void MakeZip()
{
// 圧縮する様のフォルダパス
string strFilePath = @"\\192.168.100.100\共有フォルダ\テスト\";
// ディレクトリが存在しない場合
if (Directory.Exists(strPathName) == false)
{
// ディレクトリを作成する
Directory.CreateDirectory(strPathName);
}
// ファイルコピー
File.Copy(@"\\192.168.100.100\共有フォルダ\TEST.xlsx", @"\\192.168.100.100\共有フォルダ\テスト\TEST.xlsx");
// Zip化パス
string strZip = @"\\192.168.100.100\共有フォルダ\テスト.zip";
// ディレクトリが存在しない場合
if (Directory.Exists(strZip) == false)
{
// Zip生成
ZipFile.CreateFromDirectory(strPath, strZip);
}
}
これで圧縮は出来た、が、TEST.xlsxならOKだけどもテスト.xlsxだと文字化けして失敗してしまった(デフォルトがUTF-8)。
その回避策としてCreateFromDirectoryに対し下記の様にZip生成時にパラメータを追加してエンコードを行った訳です↓
// Zip生成
ZipFile.CreateFromDirectory(strPath, strZip, CompressionLevel.Optimal, true, Encoding.GetEncoding("sjis"));
ここで問題が・・・
ここからが本題。結論から言うと CompressionLevel.Optimal ← これが.Net Frameworkバージョン4.5からでないとダメらしく、アセンブリ参照が不足していますと起こられてしまう。
※4.5以上の人は上記コードコピッペで動作します。
その他もろもろにも影響を及ぼすから~とかなんとかでバージョンを上げるって解が無い残念な弊社。かと言ってファイル名に日本語不可運用もちょっと非現実的・・・
じゃあどうするか??
DotNetZipを使用する
DotNetZipは.NET Framework 2.0以上で使用出来る強い味方。使用方法もとてもシンプルで使いやすく、古いFramework縛りならこれが最適解。ただし、本家のサイトはココなのだけれども、どこにも必要なファイルが無い(2020/10/26現在)
ここからdll直でダウンロードしてきて、プロジェクト→参照の追加で追加してさえあげれば、
以下の様な記述で文字化けせずにZip処理が出来た↓
MakeZip(DotNetZip)
using Ionic.Zip;
using Ionic.Zlib;
private void MakeZip()
{
// 圧縮するファイルパス
string strFilePass = @"\\192.168.100.100\共有フォルダ\テスト.xlsx";
// 圧縮処理
ZipFile zip = new ZipFile(Encoding.GetEncoding("shift_jis"));
zip.Password = "password";
zip.AddFile(strFilePass, "");
// ファイルの拡張子をzipに変える
strFilePass = strFilePass.Replace(Path.GetExtension(strFilePass),"") + ".zip";
zip.Save(strFilePass);
}
AddFileは第二引数に書庫内のパスを指定できるのですが、省略するとそれまでの階層が全部出来てしまう仕様。
192.168.100.100フォルダ→共有フォルダ→テスト.xlsxてな具合。
なので今回の様に単一ファイルをzipで送りたい場合等は空白指定をした方がよいですね。
後同じファイルをAddFileするとエラーになるので、重複する恐れのある実装の場合File.Exists等でチェックしましょう。
コメント