.Net?生成壓縮文件問題記錄(推薦)
一、起因
由于公司開發(fā)項目需要遷移部署到Linux環(huán)境部署運行,之前項目中生成Zip壓縮文件的代碼邏輯在Linux運行生成壓縮文件不正常。
本篇記錄文件排查處理過程。
二、問題現(xiàn)象
- 壓縮文件生成目錄不正確,文件目錄為:\root\ziptest\upgrade\_dsconnCfg.txt(項目部署目錄)
- 壓縮文件數(shù)量不正確
- 壓縮文件最后修改時間不匹配
待壓縮文件:
壓縮結(jié)果:
三、解決過程:
1、原始實現(xiàn)壓縮的主要邏輯:
using System.IO.Compression; using System.IO; /// <summary> /// 文件壓縮類 /// </summary> public class ZipHelper { /// <summary> /// 單文件壓縮成ZIP /// </summary> /// <param name="fileSource">源文件路徑</param> /// <param name="fileOut">ZIP文件路徑</param> /// <param name="fileName">ZIP文件名</param> /// <returns></returns> public static bool SimpleFileZip(string fileSource, string fileOut, string fileName) { try { using (FileStream zipFileToOpen = new FileStream(fileOut, FileMode.Create)) { using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Create)) { ZipFile(fileSource, fileName, archive); } } } catch { return false; } return true; } /// <summary> /// 多文件壓縮成ZIP /// </summary> /// <param name="fileSource">源文件路徑</param> /// <param name="fileOut">ZIP文件路徑</param> /// <param name="fileName">ZIP文件名</param> /// <returns></returns> public static bool FilesZip(List<string> fileSources, string fileOut) { try { using (FileStream zipFileToOpen = new FileStream(fileOut, FileMode.Create)) { using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Create)) { foreach (var file in fileSources) { //計算相對路徑 string fileName = file.Replace(AppConsts.ServerUpdateFile + "\\", ""); ZipFile(file, fileName, archive); } } } } catch { return false; } return true; } private static void ZipFile(string fileSource, string fileName, ZipArchive archive) { ZipArchiveEntry readMeEntry = archive.CreateEntry(fileName); //設(shè)置文件最后修改時間 readMeEntry.LastWriteTime = File.GetLastWriteTime(fileSource); using (Stream stream = readMeEntry.Open()) { byte[] bytes = File.ReadAllBytes(fileSource); stream.Write(bytes, 0, bytes.Length); } } }
2、生成路徑不正確問題:通過對代碼檢測發(fā)現(xiàn),在代碼中處理邏輯對目錄路徑替換處理時:使用了"\\";導(dǎo)致在Linux代碼無效。修改對于代碼為以下內(nèi)容:
/// <summary> /// 多文件壓縮成ZIP /// </summary> /// <param name="fileSource">源文件路徑</param> /// <param name="fileOut">ZIP文件路徑</param> /// <param name="fileName">ZIP文件名</param> /// <returns></returns> public static bool FilesZip(List<string> fileSources, string fileOut) { try { using (FileStream zipFileToOpen = new FileStream(fileOut, FileMode.OpenOrCreate)) { using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Update)) { foreach (var file in fileSources) { //計算壓縮文件相對路徑:目錄/文件名 string fileName = file.Replace(AppConsts.ServerUpdateFile + Path.DirectorySeparatorChar, ""); ZipFile(file, fileName, archive); } } } } catch (Exception ex) { Console.WriteLine($"ERROR:{ex}"); return false; } return true; }
3、排查生成文件數(shù)量異常問題,輸出異常信息。
ERROR:Cannot modify entry in Create mode after entry has been opened for writing.
at System.IO.Compression.ZipArchiveEntry.set_LastWriteTime(DateTimeOffset value)
at zlWebPluginsUpgradeServer.Upgrade.ZipHelper.ZipFile(String fileSource, String fileName, ZipArchive archive) in F:\coding\ZlsoftClientService\zlWebPluginsUpgradeServer\UpgradeMode\ZipHelper.cs:line 84
at zlWebPluginsUpgradeServer.Upgrade.ZipHelper.FilesZip(List`1 fileSources, String fileOut) in F:\coding\ZlsoftClientService\zlWebPluginsUpgradeServer\UpgradeMode\ZipHelper.cs:line 62
發(fā)現(xiàn)因為生成壓縮文件后設(shè)置最后修改時間異常,導(dǎo)致生成壓縮文件數(shù)量不正確;且最后修改時間不匹配。
4、根據(jù)日志,調(diào)整
using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Update))
到此以上在Linux中生成壓縮文件問題都已解決。
四、總結(jié):
1、代碼中路徑操作,不要使用固定字符串;應(yīng)該使用Path類提供的相關(guān)字段、方法操作
2、設(shè)置壓縮項屬性時,需要使用Update模式。
最后放上壓縮幫助類:
/// <summary> /// 文件壓縮類 /// </summary> public class ZipHelper { /// <summary> /// 單文件壓縮成ZIP /// </summary> /// <param name="fileSource">源文件路徑</param> /// <param name="fileOut">ZIP文件路徑</param> /// <param name="fileName">ZIP文件名:相對路徑</param> /// <returns></returns> public static void SimpleFileZip(string fileSource, string fileOut, string fileName) { using (FileStream zipFileToOpen = new FileStream(fileOut, FileMode.OpenOrCreate)) { using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Update)) { fileName = fileName.Trim(Path.DirectorySeparatorChar); ZipFile(fileSource, fileName, archive); } } } /// <summary> /// 多文件壓縮成ZIP /// </summary> /// <param name="fileSource">源文件路徑</param> /// <param name="fileOut">ZIP文件路徑</param> /// <param name="fileName">ZIP文件名</param> /// <returns></returns> public static void FilesZip(List<string> fileSources, string fileOut) { using (FileStream zipFileToOpen = new FileStream(fileOut, FileMode.OpenOrCreate)) { using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Update)) { foreach (var file in fileSources) { string fileName = file.Replace(AppConsts.ServerUpdateFile + Path.DirectorySeparatorChar, ""); ZipFile(file, fileName, archive); } } } } /// <summary> /// 壓縮指定文件夾 /// </summary> /// <param name="sourceDirectory"></param> /// <param name="fileOut"></param> public static void DirectoryZip(string sourceDirectory, string fileOut) { string[] allFiles = Directory.GetFiles(sourceDirectory, "", SearchOption.AllDirectories); using (FileStream zipFileToOpen = new FileStream(fileOut, FileMode.OpenOrCreate)) { using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Update)) { foreach (var file in allFiles) { //獲取壓縮文件相對目錄 string fileName = file.Replace(sourceDirectory + Path.DirectorySeparatorChar, ""); ZipFile(file, fileName, archive); } } } } /// <summary> /// 解壓文件到指定目錄 /// </summary> /// <param name="upZipDirPath"></param> /// <param name="zipPath"></param> public static void UnZip(string upZipDirPath, string zipPath) { if (!Directory.Exists(upZipDirPath)) Directory.CreateDirectory(upZipDirPath); using (FileStream zipFileToOpen = new FileStream(zipPath, FileMode.Open)) { using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Read)) { archive.ExtractToDirectory(upZipDirPath); } } } /// <summary> /// 生成壓縮文件 /// </summary> /// <param name="fileSource">源文件</param> /// <param name="fileName">壓縮文件相對目錄</param> /// <param name="archive">壓縮文件包</param> private static void ZipFile(string fileSource, string fileName, ZipArchive archive) { ZipArchiveEntry readMeEntry = archive.CreateEntry(fileName); readMeEntry.LastWriteTime = File.GetLastWriteTime(fileSource); using (Stream stream = readMeEntry.Open()) { byte[] bytes = File.ReadAllBytes(fileSource); stream.Write(bytes, 0, bytes.Length); } } }
到此這篇關(guān)于.Net 生成壓縮文件問題記錄(推薦)的文章就介紹到這了,更多相關(guān).Net 壓縮文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
asp net core2.1如何使用jwt從原理到精通(二)
這篇文章主要給大家介紹了關(guān)于asp net core2.1如何使用jwt從原理到精通的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11ASP.NET Core對不同類型的用戶進(jìn)行區(qū)別限流詳解
這篇文章主要介紹了ASP.NET Core對不同類型的用戶進(jìn)行區(qū)別限流的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02.Net使用分表分庫框架ShardingCore實現(xiàn)多字段分片
本文詳細(xì)講解了.Net使用分表分庫框架ShardingCore實現(xiàn)多字段分片的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-12-12asp.net后臺動態(tài)添加JS文件和css文件的引用實現(xiàn)方法
這篇文章主要介紹了asp.net后臺動態(tài)添加JS文件和css文件的引用實現(xiàn)方法,是非常簡單實用的技巧,需要的朋友可以參考下2014-09-09