欢迎来到代码驿站!

.NET代码

当前位置:首页 > 软件编程 > .NET代码

.Net 生成压缩文件问题记录(推荐)

时间:2022-11-14 09:32:58|栏目:.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);
        }
    }
}

上一篇:datagridview实现手动添加行数据

栏    目:.NET代码

下一篇:C#实现ProperTyGrid自定义属性的方法

本文标题:.Net 生成压缩文件问题记录(推荐)

本文地址:http://www.codeinn.net/misctech/218957.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有