星期一, 10月 19, 2020

[C#] 利用 ZipFile 進行壓縮與解壓縮

根據官方文章 - 操作說明:壓縮與解壓縮檔案 了解 ZipFile Class 使用,練習重點在於
  • 壓縮
  • 解壓縮
  • 從 Zip 檔案內解壓縮特定格式檔案

在 .Net Framework 內必須把 System.IO.Compression 和 System.IO.Compression.ZipFile 加入參考

[C#] 利用 ZipFile 進行壓縮與解壓縮-1

C# Code 練習整理
using System;
using System.IO.Compression;
using System.IO;
using System.Linq;

namespace ZipFileSample
{
    class Program
    {
        static void Main(string[] args)
        {
            // 相關路徑
            string mainPath = @"D:\ZipFileSample";
            string startPath = Path.Combine(mainPath, "Files");
            string zipPath = Path.Combine(mainPath, "result.zip");
            string extractAllPath = Path.Combine(mainPath, @"Extract\All");
            string extractImagePath = Path.Combine(mainPath, @"Extract\Image");

            // 針對資料夾進行壓縮
            if (File.Exists(zipPath)) File.Delete(zipPath);
            ZipFile.CreateFromDirectory(startPath, zipPath);

            // 確認路徑最後有 [\] 符號存在,避免 Path Traversal Attack
            if (!extractAllPath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
                extractAllPath += Path.DirectorySeparatorChar;

            // 針對 Zip File 進行解壓縮
            if (Directory.Exists(extractAllPath)) Directory.Delete(extractAllPath ,true);
            ZipFile.ExtractToDirectory(zipPath, extractAllPath);

            // 針對 ZipFile 內的 bmp 檔案進行解壓縮,把範例內的 foreach 轉為 LINQ 練習
            using (ZipArchive archive = ZipFile.OpenRead(zipPath))
            {
                archive.Entries
                    .Where(entry => entry.FullName.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase))
                    .Select(entry => new
                    {
                        entry,
                        DestinationPath = Path.GetFullPath(Path.Combine(extractImagePath, entry.FullName))
                    })
                    .ToList()
                    .ForEach(entryVar => 
                    {
                    	// Ordinal match is safest, case-sensitive volumes can be mounted within volumes that are case-insensitive.
                        if (entryVar.DestinationPath.StartsWith(extractImagePath, StringComparison.Ordinal))
                        {
                            entryVar.entry.ExtractToFile(entryVar.DestinationPath , true);
                        }
                    });
            }
        }
    }
}

文章內 Path Traversal Attack 說明
當您在解壓縮檔案時,必須尋找惡意的檔案路徑,以免它逸出您解壓縮的目的目錄。 這是所謂的路徑周遊攻擊。 以下範例示範如何檢查惡意的檔案路徑,並提供安全的方式來解壓縮。

沒有留言:

張貼留言