如何基于System.IO.Stream对象集合生成.tar文件?
如何用SharpZipLib基于Stream集合生成Tar文件
你选的方向是对的——用TarEntry.CreateEntry()手动构造条目是正确的方案,因为无法访问本地文件系统,只能基于Stream来打包。下面是具体实现步骤和代码:
核心思路
- 用
TarEntry.CreateEntry(string entryName)创建每个文件对应的条目,entryName可以包含相对路径(比如docs/report.pdf)。 - 手动设置Tar条目的关键头信息(尤其是文件大小,这是Tar包能正常解析的核心)。
- 将每个Stream的内容写入到
TarOutputStream中,完成条目后关闭当前条目。 - 所有条目处理完成后,结束Tar流的写入。
代码实现
using ICSharpCode.SharpZipLib.Tar; using System.Collections.Generic; using System.IO; // 定义文件集合:文件名(可带相对路径)+ 对应的Blob Stream var blobFileStreams = new List<(string FilePath, Stream ContentStream)> { ("notes.txt", azureBlobStream1), ("assets/logo.png", azureBlobStream2) }; // 输出Tar包的Stream(这里用MemoryStream示例,可直接上传到Azure Blob或其他存储) using var tarOutput = new TarOutputStream(new MemoryStream()); foreach (var (filePath, contentStream) in blobFileStreams) { // 创建Tar条目 var tarEntry = TarEntry.CreateEntry(filePath); // 关键:设置文件大小(需确保Stream支持Seek,Azure Blob Stream默认支持) contentStream.Position = 0; tarEntry.Size = contentStream.Length; // 可选:设置文件修改时间(可从Blob的Properties.LastModified获取) tarEntry.ModTime = DateTime.UtcNow; // 可选:设置文件权限(0644为普通文件的默认权限) tarEntry.TarHeader.Mode = 0644; // 写入条目头到Tar流 tarOutput.PutNextEntry(tarEntry); // 将Blob Stream的内容复制到Tar流 contentStream.CopyTo(tarOutput); // 关闭当前条目 tarOutput.CloseEntry(); } // 完成Tar包写入 tarOutput.Finish(); // 若要将Tar包上传到Azure Blob,可将tarOutput.BaseStream(即MemoryStream)重置位置后上传 var tarMemoryStream = (MemoryStream)tarOutput.BaseStream; tarMemoryStream.Position = 0; // await blobClient.UploadAsync(tarMemoryStream);
特殊场景处理
处理不可Seek的Stream
如果你的Stream不支持Seek(比如某些流式读取的场景),需先将内容复制到MemoryStream以获取长度:
using var tempStream = new MemoryStream(); contentStream.CopyTo(tempStream); tempStream.Position = 0; tarEntry.Size = tempStream.Length; tempStream.CopyTo(tarOutput);
创建空目录
如果需要在Tar包中创建空目录,只需创建以/结尾的条目,并设置类型为目录:
var dirEntry = TarEntry.CreateEntry("assets/"); dirEntry.TarHeader.TypeFlag = TarHeader.LF_DIR; tarOutput.PutNextEntry(dirEntry); tarOutput.CloseEntry();
内容的提问来源于stack exchange,提问作者eriyg
相关产品推荐
相关产品推荐

