Learn ASP.NET MVC, ASP.NET Core, and Design Patterns through our online training programs. Courses conducted by Bipin Joshi on weekends. Read more details here.

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.

 




Bipin Joshi is a software consultant, trainer, author and a yogi having 21+ years of experience in software development. He conducts online courses in ASP.NET MVC / Core, jQuery, AngularJS, and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced Yoga way of life he also teaches Ajapa Meditation to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 29 May 2013



Tags : ASP.NET Web Forms Data Controls