在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
鉴于许多博客讲C#打包Zip的都写的相对啰嗦且没有注释,不适合小白观看,特写此篇讲述一下 先贴代码,直接创建一个.Net Core控制台就能运行 using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; namespace Zip { class Program { static void Main(string[] args) { var zipFiles = new List<ZipFile> { new ZipFile { RelativePath = "1/2/3/公文签批单223.pdf", Content = Extend.GetBytesFromPath("E:/公文签批单.pdf") }, new ZipFile { RelativePath = "1/2/3/公文签批单2233.pdf", //相同路径下文件名重名时,解压时会提示是否覆盖 Content = Extend.GetBytesFromPath("E:/公文签批单.pdf") } }; var zipBytes = zipFiles.PackedZip(); zipBytes.WriteToFile("E:/222/Zip测试.zip"); Console.WriteLine("打包Zip成功"); Console.ReadKey(); } } public static class Extend { /// <summary> /// 将流转成字节数组 /// </summary> /// <param name="stream">文件流</param> /// <returns></returns> public static byte[] ToBytes(this Stream stream) { byte[] bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); // 设置当前流的位置为流的开始 stream.Seek(0, SeekOrigin.Begin); return bytes; } /// <summary> /// 获取文件的内容(字节数组) /// </summary> /// <param name="absolutePath">绝对路径</param> /// <returns></returns> public static byte[] GetBytesFromPath(string absolutePath) { using (Stream fileStream = new FileStream(absolutePath, FileMode.OpenOrCreate)) { return fileStream.ToBytes(); } } /// <summary> /// 字节数组写入文件 /// </summary> /// <param name="bytes">文件内容</param> /// <param name="absolutePath">绝对路径</param> public static void WriteToFile(this byte[] bytes, string absolutePath) { if (File.Exists(absolutePath)) { File.Delete(absolutePath); } using (var fs = new FileStream(absolutePath, FileMode.Create)) { fs.Write(bytes, 0, bytes.Length); } } /// <summary> /// 将Zip文件描述对象打包成Zip文件,并返回字节数组 /// </summary> /// <param name="zipFiles">Zip文件描述对象数组</param> /// <returns></returns> public static byte[] PackedZip(this List<ZipFile> zipFiles) { using (Stream memoryStream = new MemoryStream()) { using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true)) { foreach (var zipFile in zipFiles) { zipArchive.AddFile(zipFile.RelativePath, zipFile.Content); } } memoryStream.Seek(0, SeekOrigin.Begin); //这句要在using ZipArchive外面,否则压缩文件会被损坏 return memoryStream.ToBytes(); } } /// <summary> /// 向Zip文件中添加文件 /// </summary> /// <param name="zipArchive"></param> /// <param name="relativePath">相对路径</param> /// <param name="bytes">文件内容</param> /// <returns></returns> private static bool AddFile(this ZipArchive zipArchive, string relativePath, byte[] bytes) { try { ZipArchiveEntry entry = zipArchive.CreateEntry(relativePath); using (Stream entryStream = entry.Open()) { entryStream.Write(bytes, 0, bytes.Length); } return true; } catch { return false; } } } /// <summary> /// 描述打包成Zip时的一个文件的信息 /// </summary> public class ZipFile { /// <summary> /// 文件相对路径,带文件名和拓展名 /// </summary> public string RelativePath { get; set; } /// <summary> /// 字节数组(文件内容) /// </summary> public byte[] Content { get; set; } } } 打包时用的是.Net自带ZipArchive类,此类在System.IO.Compression.dll的程序集的System.IO.Compression命名空间下,一般装了VS都有,想用其他别的类库操作Zip的可以上Nuget找,但笔者写此文时用的最多就是这个 基本流程如下: 2、创建一个MemeryStream(内存流)对象,并用这个MemeryStream对象初始化ZipArchive对象(ZipArchive是.Net自带的一个操作Zip的类)【如上面代码的PackedZip方法】 p.s. 许多博客都用的物理文件初始化,那结果只能保存回那个物理文件,ZipArchive类本身不具备导出流对象的方法;但用流初始化呢,当对ZipArchive进行修改时都会同步到流对象,有了流对象就有了字节数组,我既可以保存回物理文件,也可以把流传到网络上任何地方 3、用ZipArchive对象创建ZipArchiveEntry对象,并打开ZipArchiveEntry对象的流,往流里写入文件,这样就相当于往这个Zip文件里面装文件了,创建ZipArchiveEntry对象时使用的是相对路径,文件夹不需要实际存在【如上面代码的AddFile方法】
|
请发表评论