Select
Select, Zip and Download Files displayed in a GridView
Sometime back I wrote an article that shows how to
zip and unzip files
programmatically using System.IO.Compression classes. Using these classes along
with ASP.NET controls you can allow user user to select one or more files from a
list and then programmatically "bundle" these files into a ZIP archive. Have a
look at the following figure:

As you can see from the figure a GridView control displays a list of files
that can be downloaded. A user can select desired files using checkboxes shown
in the first column of the GridView and then click on Download button. In the
click event handler of the Download button you need to zip the selected files
together and send a single ZIP file to the user for download.
Let's see how this can be done. Begin by creating a new ASP.NET web
application and add a web form to it. Place a GridView control on it and add a
template field and a BoundField to it as shown below:
<asp:GridView ID="GridView1" runat="server" SelectMethod="SelectFiles" ...>
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:TemplateField HeaderText="Download">
<EditItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server" />
</EditItemTemplate>
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server" />
</ItemTemplate>
<ItemStyle Width="5%" Wrap="False" />
</asp:TemplateField>
<asp:BoundField DataField="FileName" HeaderText="File Name" />
</Columns>
...
</asp:GridView>
<br />
<asp:Button ID="Button1" runat="server" Text="Download Selected Files" OnClick="Button1_Click" />
Notice that the template field contains a CheckBox with ID CheckBox1 and is
not bound to any data field. The BoundField is bound with FileName data field.
Also notice that the SelectMethod of the GridView is set to SelectFiles. The
SelectFiles method returns a generic List of DownloadableFile class and is shown
below:
public List<DownloadableFile> SelectFiles()
{
string[] files = Directory.GetFiles(Server.MapPath("~/downloads"));
List<DownloadableFile> downloads = new List<DownloadableFile>();
for (int i = 0; i < files.Length;i++)
{
DownloadableFile df = new DownloadableFile();
df.FileName = Path.GetFileName(files[i]);
downloads.Add(df);
}
return downloads;
}
As shown above the SelectFiles() method uses Directory class from System.IO
namespace to get a list of files from a server side folder. In this example it
is assumed that files that can be downloaded are stored in a folder named
Downloads. It then iterates through the list of files and creates
DownloadableFile instances that are bound with the GridView. In this case
DownloadableFile is a simple class with just one property:
public class DownloadableFile
{
public string FileName { get; set; }
}
If you wish to display additional information about a file such as size and
timestamp you can add additional properties to the DownloadableFile class.
Now, write the following code in the Click event handler of the Download
button.
protected void Button1_Click(object sender, EventArgs e)
{
ZipArchive zip = ZipFile.Open(Server.MapPath("~/downloads/bundle.zip"), ZipArchiveMode.Create);
foreach(GridViewRow row in GridView1.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
CheckBox cb = (CheckBox)row.FindControl("CheckBox1");
string filename=row.Cells[1].Text;
if (cb.Checked)
{
zip.CreateEntryFromFile(Server.MapPath("~/downloads/" + filename), filename);
}
}
}
zip.Dispose();
FileStream fs = File.OpenRead(Server.MapPath("~/downloads/bundle.zip"));
byte[] data = new byte[fs.Length];
fs.Read(data, 0, (int)fs.Length);
fs.Close();
File.Delete(Server.MapPath("~/downloads/bundle.zip"));
Response.Clear();
Response.AddHeader("Content-Type","application/zip");
Response.AddHeader("Content-Disposition", "inline;filename=bundle.zip");
Response.BinaryWrite(data);
Response.Flush();
}
}
The above code basically creates a ZipArchive and adds files to it based on
user selection. User selection is obtained by iterating through the Rows
collection of GridView. Once the user selection is known you can easily add
those files to a ZipArchive using CreateEntryFromFile() method. Once the ZIP
file is created, the next step is to send it to the user so that the user is
prompted to download and save the file. The code marked in bold letters does
that job.
That's it! Run the web form and test if it works as expected.