我正在编写一个库来处理Excel文件。它可以生成一个有效的.xlsx文件,除了拉链部分。
下面的代码将生成一个看起来完全有效的.ZIP文件(作为字节数组)。我可以用任何.zip工具解压缩它,没有问题。
例如,如果我接受一个.xlsx文件,将其重命名为.zip,并将所有文件解压缩到一个目录中,然后使用下面的代码进行压缩,那么将其从.zip重命名为.xlsx,Excel和LibreOffice都将拒绝打开它。
不过,我可以自己将该文件解压缩到一个文件夹中,并使用OS压缩重新压缩它们,并将其重命名为.xlsx,它将很好地打开。因此,.zip文件的内容很好。拉链本身就是问题所在。我经历了几次迭代,这是目前的情况,我只是不知道我错过了什么来满足Excel&LibreOffice的期望。我应该在条目中添加一些内容,使其成为一个更标准的.zip文件吗?
string _rootPath;
public byte[] CreateZipFile(string path)
{
_rootPath = path;
using (var ms = new MemoryStream())
using (var zipStream = new ZipOutputStream(ms))
{
RecursiveAddToZipFile(zipStream, path);
zipStream.Finish();
zipStream.Close();
return ms.ToArray();
}
}
private void RecursiveAddToZipFile(ZipOutputStream zipStream, string path)
{
foreach(var dir in Directory.GetDirectories(path))
{
var entry = new ZipEntry(dir.Replace(_rootPath, "") + @"/");
RecursiveAddToZipFile(zipStream, dir);
zipStream.PutNextEntry(entry);
zipStream.CloseEntry();
}
var files = Directory.GetFiles(path);
foreach(var file in files)
{
var entry = new ZipEntry(file.Replace(_rootPath, ""));
entry.DateTime = DateTime.Now;
zipStream.PutNextEntry(entry);
using (FileStream fs = File.OpenRead(file))
{
int totalBytes = 0;
byte[] buffer = new byte[1024 * 32];
int bytesRead;
do
{
bytesRead = fs.Read(buffer, 0, buffer.Length);
totalBytes += bytesRead;
zipStream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
entry.Size = totalBytes;
}
zipStream.CloseEntry();
}
}发布于 2022-05-06 21:29:03
根据ECMA-376-2办公室开放格式第2部分“开放包装公约”的说法,唯一支持的压缩算法是放气。因此,在将条目添加到流之前设置CompressionMethod应该会有所帮助。您的代码对此添加很好(Excel 2016成功地打开了该文件)。
var entry = new ZipEntry(dir.Replace(_rootPath, "") + @"/");
entry.CompressionMethod = CompressionMethod.Deflated;
RecursiveAddToZipFile(zipStream, dir);
zipStream.PutNextEntry(entry);
zipStream.CloseEntry();https://stackoverflow.com/questions/72146862
复制相似问题