问题记录- .Net 生成压缩文件问题
Posted One To One
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了问题记录- .Net 生成压缩文件问题相关的知识,希望对你有一定的参考价值。
一、起因
由于公司开发项目需要迁移部署到Linux环境部署运行,之前项目中生成Zip压缩文件的代码逻辑在Linux运行生成压缩文件不正常。
本篇记录文件排查处理过程。
二、问题现象
- 压缩文件生成目录不正确,文件目录为:\\root\\ziptest\\upgrade\\_dsconnCfg.txt(项目部署目录)
- 压缩文件数量不正确
- 压缩文件最后修改时间不匹配
待压缩文件:
压缩结果:
三、解决过程:
1、原始实现压缩的主要逻辑:
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);
//设置文件最后修改时间 readMeEntry.LastWriteTime = File.GetLastWriteTime(fileSource); using (Stream stream = readMeEntry.Open()) byte[] bytes = File.ReadAllBytes(fileSource); stream.Write(bytes, 0, bytes.Length);
2、生成路径不正确问题:通过对代码检测发现,在代码中处理逻辑对目录路径替换处理时:使用了"\\\\";导致在Linux代码无效。修改对于代码为以下内容:
/// <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、排查生成文件数量异常问题,输出异常信息。
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
发现因为生成压缩文件后设置最后修改时间异常,导致生成压缩文件数量不正确;且最后修改时间不匹配。
4、根据日志,调整
using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Update))
到此以上在Linux中生成压缩文件问题都已解决。
四、总结:
1、代码中路径操作,不要使用固定字符串;应该使用Path类提供的相关字段、方法操作
2、设置压缩项属性时,需要使用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);
以上是关于问题记录- .Net 生成压缩文件问题的主要内容,如果未能解决你的问题,请参考以下文章