简体   繁体   English

c#下载由Web应用程序创建的文件的zip存档

[英]c# downloading a zip archieve of files created by web application

using Ionic.Zip
...
using (ZipFile zip = new ZipFile())
    {
        zip.AlternateEncodingUsage = ZipOption.AsNecessary;
        zip.AddDirectoryByName("Files");
        foreach (GridViewRow row in GridView1.Rows)
        {
            if ((row.FindControl("chkSelect") as CheckBox).Checked)
            {
                string filePath = (row.FindControl("lblFilePath") as Label).Text;
                zip.AddFile(filePath, "Files");
            }
        }
        Response.Clear();
        Response.BufferOutput = false;
        string zipName = String.Format("Zip_{0}.zip", DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
        Response.ContentType = "application/zip";
        Response.AddHeader("content-disposition", "attachment; filename=" + zipName); 
        zip.Save(Response.OutputStream);
        Response.End();
    }

Hello! 你好! This portion of code does the downloading of a zipped directory. 这部分代码用于下载压缩目录。 Let's say I have a gridview of CONTENTS of text files I want to download. 假设我要下载的文本文件包含一个gridview。 Is there a way of making the program download such archieve without knowing or writing the paths to files? 有没有一种方法可以使程序在不知道或不写文件路径的情况下下载此类文件?

The code should work this way: 该代码应以这种方式工作:

1. get item from gridview 
2. create a text file from the content
3. add it to the zip directory
(repeat foreach item in gridview)
n. download a zipped file

According to the documentation, you can add an entry from a Stream . 根据文档,您可以Stream添加一个条目 So consider where you currently do this: 因此,请考虑您当前在哪里执行此操作:

zip.AddFile(filePath, "Files");

Instead of adding a "file" given a path, you'd add a "file" given a stream of data. 无需添加给定路径的“文件”,而是添加给定数据流的“文件”。

So you can create a stream from a string: 因此,您可以从字符串创建流:

new MemoryStream(Encoding.UTF8.GetBytes(someString)) // or whatever encoding you use

and add it to the Zip: 并将其添加到Zip:

using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(someString)))
{
    zip.AddEntry(someFileName, stream);
    // other code
    zip.Save(Response.OutputStream);
}

One thing to note here is that your resource management and disposal (with the using blocks) might get a little tricky. 这里要注意的一件事是,您的资源管理和处置(带有using块) 可能会有些棘手。 This is because, according to the documentation: 这是因为,根据文档:

The application should provide an open, readable stream; 该应用程序应提供一个开放的,可读的流; in this case it will be read during the call to Save() or one of its overloads. 在这种情况下,将在调用Save()或其重载之一期间读取它。

What this means is that if you dispose of any of the streams before calling .Save() , it will fail when you call it. 这意味着,如果您调用.Save() 之前处置了任何流,则调用它时将失败。 You might want to look through the documentation some more to see if there's a way to force the Zip to read the streams earlier in the process. 您可能需要仔细阅读文档,以了解是否有一种方法可以强制Zip在此过程的早期读取流。 Otherwise you're basically going to have to manage a bunch of open streams until it's time to "save" the Zip. 否则,您基本上必须管理一堆开放流,直到需要“保存” Zip为止。


Edit: It looks like the documentation was right there ... 编辑:看起来文档就在那里 ...

In cases where a large number of streams will be added to the ZipFile, the application may wish to avoid maintaining all of the streams open simultaneously. 在将大量流添加到ZipFile的情况下,应用程序可能希望避免同时保持所有流打开。 To handle this situation, the application should use the AddEntry(String, OpenDelegate, CloseDelegate) overload. 要处理这种情况,应用程序应使用AddEntry(String,OpenDelegate,CloseDelegate)重载。

This will be a little more complex and will require you to open/close/dispose your streams manually in your delegates. 这会稍微复杂一点,将需要您在代理中手动打开/关闭/处理流。 So it's up to you as you build your logic whether this is preferable to nesting your using blocks. 因此,这取决于您构建逻辑是否比嵌套您的using块更可取。 It'll likely depend on how many streams you plan to use. 这可能取决于您计划使用多少个流。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM