C# MemoryStream.CopyTo(fileStream) 添加额外字节并损坏 OpenXML 文件

C# MemoryStream.CopyTo(fileStream) adding extra bytes and corrupting OpenXML file

我正在使用 OpenXML 生成 Excel 电子表格。

我正在 MemoryStream 中生成电子表格;调用者正在写出实际文件。例如,我的 .Net Core 控制器将 return 内存流作为 FileResult。目前,我有一个正在编写 FileStream 的独立控制台模式程序。

问题:我在文件末尾得到了额外的字节。由于 OpenXml .xlsx 文件是 .zip 文件,因此额外的字节实际上会损坏文件。

Program.cs:

using (MemoryStream memoryStream = new MemoryStream())
{
    OpenXMLGenerate(memoryStream, sampleData);
    long msPos = memoryStream.Position;  // Position= 1869: Good!
    memoryStream.Position = 0;
    using (FileStream fs = new FileStream("myfile.xlsx", FileMode.OpenOrCreate))
    {
        memoryStream.WriteTo(fs);
        long fsPos = fs.Position;  // Position= 1869: Good!
    }
    // Myfile.xlsx filesize= 2014, not 1869! Bad!!!
}

当我在 7-Zip 中打开文件时,它显示:

Warnings: There are some data after the end of the payload data

Physical Size: 1869

Tail Size: 145

当我尝试将其作为 .zip 文件打开时,Windows 显示:

The Compressed (zipped) folder is invald.

问:知道为什么我得到的是 2014 字节的文件,而不是 1869 字节的文件吗?

问:我该怎么办?

(根据评论记录。)这个问题可以通过替换长度为 2014 字节的现有文件的文件来解释。

如果引用的文件存在,使用 FileMode.OpenOrCreate 模式创建文件流等同于使用 FileMode.Open。如果内存流的长度小于现有文件的长度,则现有文件不会被截断为内存流的长度;在这种情况下,如果 N 是内存流的长度,则现有文件的前 N ​​个字节将被内存流的内容覆盖,其余字节将保留在原始文件中。

创建文件模式为 FileMode.Create 的文件流将完全替换现有文件(如果存在),消除新文件将包含现有文件残余的任何可能性。