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

 更新时间:2022年02月28日 09:46:33   作者:One To One  
由于公司开发项目需要迁移部署到Linux环境部署运行,之前项目中生成Zip压缩文件的代码逻辑在Linux运行生成压缩文件不正常,今天通过本文给大家分享.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 压缩文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • asp.net快速连接access

    asp.net快速连接access

    网上有很多人在问asp.net连接access的问题,作为一个程序员,我觉得非常有必要分享一下我是怎么快速,简单连接access数据库的。本经验采用HTML代码结合JS模式,直接写在网页中,非常适合学习新手。
    2015-09-09
  • .NET中STAThread的使用详解

    .NET中STAThread的使用详解

    这个STA线程模型,在线程内加入了讯息帮浦等等机制,减少开发人员撰写窗口程序的工作量
    2013-05-05
  • .Net防sql注入的几种方法

    .Net防sql注入的几种方法

    这篇文章主要给大家总结介绍了关于.Net防sql注入的几种方法,文中通过示例代码介绍的非常详细,对大家学习或者使用.Net具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • MVC4制作网站教程第四章 部分栏目功能实现代码

    MVC4制作网站教程第四章 部分栏目功能实现代码

    这篇文章主要为大家详细介绍了MVC4制作网站教程,部分栏目功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • Prism区域管理器IRegionManager用法介绍

    Prism区域管理器IRegionManager用法介绍

    这篇文章介绍了Prism区域管理器IRegionManager用法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-02-02
  • Gridview利用DataFormatString属性设置数据格式的方法

    Gridview利用DataFormatString属性设置数据格式的方法

    这篇文章主要介绍了Gridview利用DataFormatString属性设置数据格式的方法,涉及Gridview属性操作及数据格式相关技巧,需要的朋友可以参考下
    2016-03-03
  • 用Html5与Asp.net MVC上传多个文件的实现代码

    用Html5与Asp.net MVC上传多个文件的实现代码

    Html 5 的有一些File API,对Form表单增强的特性,让我们轻松支持多文件上传,看下面的Html片断代码
    2012-08-08
  • 理解HttpHandler,并为所有*.jpg图片生成一段文字于图片上

    理解HttpHandler,并为所有*.jpg图片生成一段文字于图片上

    HttpHandler就是最终相应HTTP请求,生成HTTP响应的处理器,他们的实例由asp.net运行时创建,,并生存在asp.net的运行时环境中,如果asp.net运行时是处理请求的工厂,HttpHandler是处理请求的工人
    2012-03-03
  • C# 文件上传 默认最大为4M的解决方法

    C# 文件上传 默认最大为4M的解决方法

    .net中默只能上传小于4m的文件,大于4M将无法显示页面.那么如何设置来使imputfile能上传更大的文件呢
    2008-11-11
  • asp.net core多文件分块同时上传组件使用详解

    asp.net core多文件分块同时上传组件使用详解

    这篇文章主要为大家介绍了一个可多个文件同时上传、断点续传,并实时反馈上传进度的 Asp.Net core 组件,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12

最新评论