.NET 建立加密ZIP
之前有一篇是 走訪資料夾及Web下載檔案(zip) 這篇 主要使用的是 ZipArchive
System.IO.Compression 名命空間裡提供一個類別 ZipArchive
但是這個類別有一個問題 那就是無法加密。
接著因為工作需求,老闆叫我搞一個加密的,因此有了這篇文章
主要還是依照 走訪資料夾及Web下載檔案(zip) 的概念 但是這次使用的是DotNetZip
{
//目前抓前一天 可修改
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;
}
}
}
}
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/
留言
張貼留言