.NET 建立加密ZIP

 之前有一篇是 走訪資料夾及Web下載檔案(zip) 這篇 主要使用的是 ZipArchive 

System.IO.Compression 名命空間裡提供一個類別 ZipArchive


但是這個類別有一個問題 那就是無法加密。

接著因為工作需求,老闆叫我搞一個加密的,因此有了這篇文章

主要還是依照 走訪資料夾及Web下載檔案(zip) 的概念 但是這次使用的是DotNetZip

static void Main(string[] args)
        {
            //目前抓前一天 可修改
            DateTime Start = DateTime.Parse(DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd 00:00:00.000"));
            DateTime End = DateTime.Parse(DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd 23:59:59.999"));
            List<model> lsResponse = ModelData();
            string nasPath = ConfigurationManager.AppSettings["nasPath"];
            string xmlPath = ConfigurationManager.AppSettings["xmlPath"];
            //目前數量 控管在2000內
            int iCount = 0;
            //建檔使用 用於串字串
            int pathCount = 0;
            //不存在則寫log 建立資料夾
            if (!Directory.Exists(xmlPath))
            {
                log.DebugFormat("Directory Path Not Exists : {0}", xmlPath);
                Directory.CreateDirectory(xmlPath);
            }
                List<string> lsData = new List<string>();
                //設定Path 指向目標檔案目的地
                var tempXml = xmlPath;
                    //計數器 2000後輸出
                    iCount++;
                   OutputModel OutputJson = new OutputModel() {
                        Token = list.Token,
                        OutputJson = list.OutputJson,
                        CreateTime = list.CreateTime
                    };
                    string data = JsonConvert.SerializeObject(OutputJson);
                    lsData.Add(data);
                    //2000 筆 輸出後清空
                    if (iCount == 2000)
                    {
                        tempXml = xmlPath + "SupplementaryFile_" + (pathCount++) + ".xml";
                        File.WriteAllLines(tempXml, lsData);
                        lsData = new List<string>();
                        iCount = 0;
                    }
                //沒寫完則寫完
                if (iCount != 0)
                {
                    tempXml = xmlPath + "SupplementaryFile_" + pathCount + ".xml";
                    File.WriteAllLines(tempXml, lsData);
                }
                //建立Zip並且清空xml
                GetZip_PassWord(xmlPath, nasPath + "File\\" + OutputPath, DateTime.Now.ToString("yyyyMMdd"));
        }
        public static void GetZip_PassWord(string dataPath, string savePath, string passWord)
        {
            // 1.------------- 建立檔案名稱以及走訪目標區域
            //zip檔案名稱 這段主要是在取zip等等的名稱,這段單純是在取名字而已
            string zipSteamName = savePath + DateTime.Now.ToString("yyyy_MM_dd") + ".zip";
            //不存在則寫log 建立資料夾
            if (!Directory.Exists(savePath.Substring(0, savePath.LastIndexOf('\\'))))
            {
                log.DebugFormat("[FETC_API_SupplementaryFile] Directory Path Not Exists : {0}", savePath.Substring(0, savePath.LastIndexOf('\\')));
                Directory.CreateDirectory(savePath.Substring(0, savePath.LastIndexOf('\\')));
            }
            //這段的目的在於鎖定走訪的路徑
            //取得目標檔案路徑
            DirectoryInfo di = new DirectoryInfo(dataPath);
            //取得目標pdf資料夾內pdf資料陣列
            FileInfo[] files = di.GetFiles();
            using (var zip = new ZipFile())
            {
                zip.Password = passWord;
                //走訪file資料夾
                foreach (var fileinfo in files)
                {
                    //取得新檔案 f = file 內含pdf資料夾內資料走訪
                    FileStream f = new FileStream(fileinfo.FullName, FileMode.Open, FileAccess.Read);
                    //取得filestream 成 byte array
                    zip.AddEntry("Token.txt", StringReadToEnd(f));
                    //歸還空間 這邊不歸還的話沒辦法關掉file 會導致file卡死無法操作
                    f.Dispose();
                    f.Close();
                }
                zip.Save(zipSteamName);
            }
        }
        public static string StringReadToEnd(Stream stream)
        {
            //目前stream位置
            long originalPosition = 0;
            //若stream可支援搜尋的話
            //檢查是否有選定從某個點開始
            if (stream.CanSeek)
            {
                //目前位置 = stream位置
                originalPosition = stream.Position;
                //stream 歸零
                stream.Position = 0;
            }
            try
            {
                //byte array儲存區
                byte[] readBuffer = new byte[4096];
                //目前讀取位置 起始點
                int totalBytesRead = 0;
                //目前讀取位置 結束點
                int bytesRead;
                //一次抓4096個長度 抓到-1的時候停止
                //計算目前讀到哪一位數 從totalBytesRead開始讀 讀 readbuffer - 曾經讀過的長度
                //也就是從 array0開始 讀取 4096個 因此是 0 ~ 4095陣列有值
                //如果讀取長度超過的話則不會讀取值
                //如一個長度為10000的資料 讀取長度為 16000 讀取還是只會回饋 10000 而非 16000 
                while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
                {
                    //目前讀到的長度
                    totalBytesRead += bytesRead;
                    //假如長度相同的話 代表還沒讀滿
                    if (totalBytesRead == readBuffer.Length)
                    {
                        //取目前讀的下一個值
                        int nextByte = stream.ReadByte();
                        //計算目前要讀的下一個是否有值 沒值是-1
                        if (nextByte != -1)
                        {
                            //建立一個大兩倍的空間 不夠大就繼續兩倍成長空間來讀取程式
                            byte[] temp = new byte[readBuffer.Length * 2];
                            //從readBuffer 0位開始複製整個readbuffer到temp中 
                            Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
                            //在上一個空間最大值中塞入一位byte
                            //(原理是因為 4096長度的空間是為 0 ~ 4095 因此在4096塞入一位 變成4097長度) 
                            //且因為讀取了值 因此不寫入的話會遺漏
                            Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
                            //複製temp的空間大小給readbuffer
                            readBuffer = temp;
                            //因為readbuffer有多加一位 因此+1
                            totalBytesRead++;
                        }
                    }
                }
                //輸出readbuffer
                byte[] buffer = readBuffer;
                if (readBuffer.Length != totalBytesRead)
                {
                    //建立一個buffer 他的長度為剛剛測定的全長
                    buffer = new byte[totalBytesRead];
                    //複製readBuffer的資料從頭到尾進入buffer內
                    Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
                }
                string strOutput = "";
                strOutput += System.Text.Encoding.UTF8.GetString(buffer);
                return strOutput;
            }
            finally
            {
                //若可以搜尋的話
                if (stream.CanSeek)
                {
                    //資料流位置 = 目前stream位置
                    //更新stream位置回最初位置
                    stream.Position = originalPosition;
                }
            }
        }
    }
參考的code

static void Main(string[] args)

        {

            //建立zip

            using (var zip = new ZipFile())

            {

                zip.Password = "P@ssW0rd";

                //建立zip內容

                zip.AddEntry("imgs\\chart.png", GenChart());

                zip.AddEntry("index.html", $@"

<html><body>

    <div>{DateTime.Today:yyyy-MM-dd} 業績</div>

    <img src='imgs/chart.png' />

</body>");

                zip.Save("D:\\Secret.zip");

            }

        }


        static byte[] GenChart()

        {

            var bmp = new Bitmap(240, 180);

            var g = Graphics.FromImage(bmp);

            g.FillRectangle(new SolidBrush(Color.LightGray),

                0, 0, bmp.Width, bmp.Height);

            var p = new Pen(new SolidBrush(Color.Black));

            var margin = 6;

            g.DrawRectangle(p, margin, margin, 1, bmp.Height - margin * 2);

            g.DrawRectangle(p, margin, bmp.Height - margin, bmp.Width - margin * 2, 1);

            var colors = new Color[]

            {

                Color.Green,

                Color.Brown,

                Color.BlueViolet,

                Color.Indigo

            };

            var barAreaWidth = (bmp.Width - margin * 2) / 4;

            var barWidth = 40;

            var rnd = new Random();

            Enumerable.Range(0, 4).ToList()

                .ForEach(i =>

                {

                    var value = rnd.Next(120) + 50;

                    g.FillRectangle(new SolidBrush(colors[i]), 

                        margin + i * barAreaWidth + (barAreaWidth - barWidth) / 2, 

                        bmp.Height - margin - value, 

                        barWidth, 

                        value);

                });

            using (var ms = new MemoryStream())

            {

                bmp.Save(ms, ImageFormat.Png);

                return ms.ToArray();

            }

        }

參考:

https://blog.darkthread.net/blog/encrypted-zip-on-the-fly/

留言

這個網誌中的熱門文章

無法載入檔案或組件 'System.IO.Compression' 或其相依性的其中之一。

MongoDB 入門

DDD With MVC