简体   繁体   中英

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. 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 . 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:

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. 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.

What this means is that if you dispose of any of the streams before calling .Save() , it will fail when you call it. 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. Otherwise you're basically going to have to manage a bunch of open streams until it's time to "save" the 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. To handle this situation, the application should use the AddEntry(String, OpenDelegate, CloseDelegate) overload.

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. It'll likely depend on how many streams you plan to use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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