如何使用ZipFile.CreateFromDirectory将压缩包写入MemoryStream而非输出路径?
解决ZipFile.CreateFromDirectory写入MemoryStream的问题
没错,你观察得很准——ZipFile.CreateFromDirectory确实没有直接输出到MemoryStream的重载,它只能指定一个文件路径作为压缩输出目标。所以你有两个可行的解决方案,不用太纠结,看你更看重哪种需求:
方案1:借助临时文件(简单但有IO开销)
如果项目对性能要求不是极致苛刻,用临时文件中转是最省心的方式:
using (var ms = new MemoryStream()) { // 创建临时文件路径 string tempZipPath = Path.GetTempFileName(); try { // 先压缩到临时文件 ZipFile.CreateFromDirectory(path, tempZipPath); // 把临时文件读进MemoryStream using (var fileStream = new FileStream(tempZipPath, FileMode.Open, FileAccess.Read)) { fileStream.CopyTo(ms); } buf = ms.ToArray(); LogZipFile(path, filesize, buf.LongLength); } finally { // 用完删除临时文件 File.Delete(tempZipPath); } }
方案2:手动使用ZipArchive(无IO开销,稍复杂)
如果不想碰磁盘IO,那就得手动用ZipArchive来遍历目录并添加文件,这也是你猜测的“自行生成”的方式,其实代码也不算复杂:
using (var ms = new MemoryStream()) { using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true)) { // 获取要压缩的目录下的所有文件(包括子目录) var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories); foreach (var file in files) { // 计算文件在压缩包内的相对路径 string entryName = Path.GetRelativePath(path, file); // 创建压缩包条目并写入文件内容 var entry = archive.CreateEntry(entryName); using (var entryStream = entry.Open()) using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) { fileStream.CopyTo(entryStream); } } } buf = ms.ToArray(); LogZipFile(path, filesize, buf.LongLength); }
这里要注意ZipArchive的第三个参数leaveOpen设为true,这样在ZipArchive释放后,MemoryStream还能继续使用来转换字节数组。
两种方案各有优劣:方案1代码简单易维护,方案2避免了磁盘操作,适合对性能敏感的场景。你可以根据自己的需求选~
内容的提问来源于stack exchange,提问作者jefflahh
相关产品推荐
相关产品推荐

