ZipArchive返回空文件 c#

4

我已经成功地压缩了文件,但现在我又遇到了另一个问题,压缩文件夹中包含空文件。压缩后的文件大小为0字节。

以下是我压缩文件的方法:

try
{
    var outPutDirectory = AppDomain.CurrentDomain.BaseDirectory;
    string logoimage = Path.Combine(outPutDirectory, "images\\error.png");

    HttpContext.Current.Response.Clear();
    HttpContext.Current.Response.BufferOutput = false;
    HttpContext.Current.Response.ContentType = "application/zip";
    HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=pauls_chapel_audio.zip");

    using (MemoryStream ms = new MemoryStream())
    {
        // create new ZIP archive within prepared MemoryStream
        using (ZipArchive zip = new ZipArchive(ms, ZipArchiveMode.Create, true))
        {
            var demoFile = zip.CreateEntry(logoimage);
            // add some files to ZIP archive
        }
        ms.WriteTo(HttpContext.Current.Response.OutputStream);
    }

    return true;
}

另一个问题是压缩文件夹与图像具有相同的路径。因此,它就像...

ZippFolder/A/B/C/image...

我只需要

ZipFolder/content

1
嗯,有两件事情。1. 你的代码似乎是ASP.NET而不是C#特定的?2. 你正在创建一个很好的内存流,但它从未被“准备”,也就是没有设置任何内容? - Thomas
我不确定如何编写它。我是新手,你能给个例子吗? - mohsinali1317
HttpContext听起来像是asp.net中的一些内容,因此您应将该标签添加到您的问题中。至于MemoryStream,您可以使用new MemoryStream()创建一个空内存流,但这只是创建了一个空内存流,您并没有设置数据源(由于我不知道您项目的更多细节,我无法确定如何设置/初始化它)。您应该添加数据源应该来自哪里,如果是来自文件下载/上传对话框等... - Thomas
目前它来自一个静态文件。 - mohsinali1317
1
但整个东西应该是一个Web应用程序吗? - Thomas
我建议你在这里查看:https://dev59.com/yG025IYBdhLWcg3wHR4Y 因为你需要的是一个文件流而不是内存流。 - Thomas
1个回答

6
var demoFile = zip.CreateEntry(logoimage);

这将在ZIP文件中创建一个名为logoimage的条目(即完整路径为/A/B/C/images/error.png或其他路径)。
但您从未向该条目写入任何内容,因此它是空的。如果您想要不同的路径,应在此指定:
var demoFile = zip.CreateEntry("content\\error.png");
using (StreamWriter writer = new StreamWriter(demoFile.Open()))
using (StreamReader reader = new StreamReader(logoimage))
{
    writer.Write(reader.ReadToEnd());
}

另外,您也可以完全跳过StreamWriter,直接向流中写入:

using (Stream stream = demoFile.Open())
using (StreamReader reader = new StreamReader(logoimage))
{
    reader.BaseStream.CopyTo(stream);
}

顺便提一下,你可以跳过你想要先将zip文件写入的外部MemoryStream,然后将该流写入OutputStream。相反,你可以直接向该流写入。只需将其传递给ZipFile构造函数即可:

Stream output = HttpContext.Current.Response.OutputStream;
using (ZipArchive zip = new ZipArchive(output, ZipArchiveMode.Create, true))
{
    …
}

他能不能直接使用 .CopyTo HttpContext.Current.Response.OutputStream,而不是使用 writer,因为他想把数据放在那里。 - Thomas
问题不在于将输出放入输出流中,而在于他想从HTTP请求中返回一个压缩文件,但他从未将实际内容添加到zip中。 - poke
@ChaudhryMohsinAli 对不起,搞混了。CopyTo只适用于流,而不适用于StreamReaders/Writers。 - poke
现在图像大小为26 KB,但它已经损坏或出现了某些问题。原始图像大约为15 KB。 - mohsinali1317
@Thomas 是的,你可以完全跳过MemoryStream,直接将ZipFile写入OutputStream。但是你需要以正常方式读取文件并将其传递给ZipFile。 - poke
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接