.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 生成压缩文件问题记录(推荐)的文章就介绍到这了,更多相关.Net 压缩文件内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341