.net 为电子邮件附件压缩MemoryStream

.net 为电子邮件附件压缩MemoryStream,.net,zip,attachment,deflatestream,.net,Zip,Attachment,Deflatestream,我正在尝试压缩XML树并将其用作电子邮件附件。发送带有附件的电子邮件成功,但创建的zip文件始终损坏–它不是有效的zip文件,但包含二进制数据 此问题将按如下方式重新创建,具体请参见BuildAttachment(): 把问题放在上下文中:它是windows服务应用程序的一部分,所以我不想在磁盘上创建文件,电子邮件还包含xslt转换的xml树的替代视图,所以我不想使用完全不同的解决方案 有任何关于zip文件损坏原因的建议吗?您不是在创建有效的zip文件,而是在创建压缩流并将其写入扩展名为*.zi

我正在尝试压缩XML树并将其用作电子邮件附件。发送带有附件的电子邮件成功,但创建的zip文件始终损坏–它不是有效的zip文件,但包含二进制数据

此问题将按如下方式重新创建,具体请参见
BuildAttachment()

把问题放在上下文中:它是windows服务应用程序的一部分,所以我不想在磁盘上创建文件,电子邮件还包含xslt转换的xml树的替代视图,所以我不想使用完全不同的解决方案


有任何关于zip文件损坏原因的建议吗?

您不是在创建有效的zip文件,而是在创建压缩流并将其写入扩展名为
*.zip的文件。您应该使用.NET zip库,而不是
DeflateStream

您可以使用以下内容:

DotNetZip是一个易于使用、快速、免费的类库和工具集 操作zip文件或文件夹。压缩和解压缩很容易:使用 用VB、C#-任何.NET语言编写的.NET应用程序- 可以轻松创建、读取、提取或更新zip文件。单声道或多声道 .NET

如果您有限制并且无法使用外部库,您可以尝试使用
GZipStream
,并添加扩展名为
*.gz
的附件,这将由常用压缩工具支持


作为将来参考的有用信息,.NET 4.5最终将通过该类引入对zip存档的本机支持。

为了将来参考,可接受答案中建议的生成.gz存档的备用
GZipStream
方法通过如下更改上述代码来实现

static Attachment BuildAttachment(XElement report)
{
    var inStream = new MemoryStream();
    report.Save(inStream);
    inStream.Position = 0;

    var outStream = new MemoryStream();
    using (var compress = new GZipStream(outStream, CompressionMode.Compress))
    {
        inStream.CopyTo(compress);
        compress.Close();
    }

    var ms = new MemoryStream(outStream.ToArray());
    Attachment attachment = new Attachment(ms, "report.xml.gz", "application/gzip");
    return attachment;
}

需要使用
using
块和
ToArray()
调用

我知道这是一个老问题,但当我在寻找同样的问题时,它出现了

下面是我使用[基于ACRAI5075的答案]添加压缩(zip)附件的解决方案:

byte[] report = GetSomeReportAsByteArray();
string fileName = "file.txt";

using (MemoryStream memoryStream = new MemoryStream())
{
    using (ZipArchive zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Update))
    {
        ZipArchiveEntry zipArchiveEntry = zipArchive.CreateEntry(fileName);
        using (StreamWriter streamWriter = new StreamWriter(zipArchiveEntry.Open()))
        {
            streamWriter.Write(Encoding.Default.GetString(report));
        }
    }

    MemoryStream attachmentStream = new MemoryStream(memoryStream.ToArray());

    Attachment attachment = new Attachment(attachmentStream, fileName + ".zip", MediaTypeNames.Application.Zip);
    mail.Attachments.Add(attachment);
}
多亏了“Neils.R”的回答,我创建了一个静态C#函数来管理附件,并在超过1Mb时将其压缩。希望这对任何人都有帮助

public static Attachment CreateAttachment(string fileNameAndPath, bool zipIfTooLarge = true, int bytes = 1 << 20)
{
    if (!zipIfTooLarge)
    {
        return new Attachment(fileNameAndPath);
    }

    var fileInfo = new FileInfo(fileNameAndPath);
    // Less than 1Mb just attach as is.
    if (fileInfo.Length < bytes)
    {
        var attachment = new Attachment(fileNameAndPath);

        return attachment;
    }

    byte[] fileBytes = File.ReadAllBytes(fileNameAndPath);

    using (var memoryStream = new MemoryStream())
    {
        string fileName = Path.GetFileName(fileNameAndPath);

        using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create))
        {
            ZipArchiveEntry zipArchiveEntry = zipArchive.CreateEntry(fileName, CompressionLevel.Optimal);

            using (var streamWriter = new StreamWriter(zipArchiveEntry.Open()))
            {
                streamWriter.Write(Encoding.Default.GetString(fileBytes));
            }
        }

        var attachmentStream = new MemoryStream(memoryStream.ToArray());
        string zipname = $"{Path.GetFileNameWithoutExtension(fileName)}.zip";
        var attachment = new Attachment(attachmentStream, zipname, MediaTypeNames.Application.Zip);

        return attachment;
    }
}

public static Attachment CreateAttachment(string fileNameAndPath,bool zipIfTooLarge=true,int bytes=1
DeflateStream!=Zip文件
(.Zip可以有多种压缩类型)可能与此重复。不过,我必须将ZipArchiveMode设置为Create。
public static Attachment CreateAttachment(string fileNameAndPath, bool zipIfTooLarge = true, int bytes = 1 << 20)
{
    if (!zipIfTooLarge)
    {
        return new Attachment(fileNameAndPath);
    }

    var fileInfo = new FileInfo(fileNameAndPath);
    // Less than 1Mb just attach as is.
    if (fileInfo.Length < bytes)
    {
        var attachment = new Attachment(fileNameAndPath);

        return attachment;
    }

    byte[] fileBytes = File.ReadAllBytes(fileNameAndPath);

    using (var memoryStream = new MemoryStream())
    {
        string fileName = Path.GetFileName(fileNameAndPath);

        using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create))
        {
            ZipArchiveEntry zipArchiveEntry = zipArchive.CreateEntry(fileName, CompressionLevel.Optimal);

            using (var streamWriter = new StreamWriter(zipArchiveEntry.Open()))
            {
                streamWriter.Write(Encoding.Default.GetString(fileBytes));
            }
        }

        var attachmentStream = new MemoryStream(memoryStream.ToArray());
        string zipname = $"{Path.GetFileNameWithoutExtension(fileName)}.zip";
        var attachment = new Attachment(attachmentStream, zipname, MediaTypeNames.Application.Zip);

        return attachment;
    }
}