Adding multiple files selected from GridView? C#

Jan 13, 2010 at 6:56 PM

Hello, I am new to C# and ASP.net...I have tried different ways to add multiple files to one .zip file that were selected from a GridView with no results.  This is a logo repository where the end user selects logos by clicking checkboxes.  A style guide is included with each zip file for guidelines on the use of the logo.    I click multiple boxes and it only zips the first checkbox that is selected.  Here is the original code:

protected void btnZip_Click(object sender, EventArgs e)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            string fileName = String.Empty;
            string ZipFileName = Server.MapPath(@"TempFiles/" + Guid.NewGuid().ToString() + ".zip");
            string local_path = tvDirTree.SelectedNode.Value.ToString();
            local_path = "." + local_path.Substring(local_path.IndexOf("file_repository") - 1, (local_path.Length - local_path.IndexOf("file_repository")) + 1).Replace("\\", "/");
            
           // Iterate through the Products.Rows property
            foreach (GridViewRow row in dgFiles.Rows)
            {
                // Access the CheckBox
                CheckBox cb = (CheckBox)row.FindControl("chkSelect");
                if (cb != null && cb.Checked)
                {
                    fileName = (row.FindControl("lblFileName") as Label).Text;
                   
                    Response.Clear();
                    Response.BufferOutput = false;
                    string archiveName = String.Format("archive-{0}.zip", DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
                   
                    using (ZipFile zip = new ZipFile())
                    {
                             // filesToInclude is a IEnumerable (String[] or List etc)
                            zip.AddFile(Server.MapPath(local_path + "//" + fileName), "");
                            zip.AddFile(Server.MapPath(local_path + "//" + "styleguide.docx"), "");
                            zip.Save(ZipFileName);
                       
                    }

                     // Response.End();

                    Response.ContentType = "application/zip";
                    Response.AppendHeader("Content-Disposition", "attachment; filename=" + archiveName);
                    Response.WriteFile(ZipFileName);

                    Response.Flush();
                    Response.Close();

                    // delete the temp file
                    if (File.Exists(ZipFileName))
                        File.Delete(ZipFileName);

                   
                   
                    HttpContext.Current.ApplicationInstance.CompleteRequest();

                    sb.Append(String.Format("Folder {0} Zipped successfuly to File {1}.<br/>", local_path, ZipFileName));

                }

                lbReport.Text = sb.ToString();
            }
        }
    }

Any suggestions?  Any help is greatly appreciated!!

Coordinator
Jan 13, 2010 at 7:29 PM
Edited Jan 13, 2010 at 7:48 PM

Yes, there's a basic error in logic flow.

You have a loop that begins foreach (GridViewRow row in dgFiles.Rows)...   Within that loop, you create a zip file, add a couple of files to it, save it, and write it out the the Response stream.  Then you close the response stream.  What gets sent is a zip file with exactly 2 files in it.   Once the Response stream is closed, you cannot re-open it.  Therefore, the next loop through the foreach, you are doing nothing. 

If I understand what you're shooting for, I think what you want is the ZipFile.Save() and Response.Close() to be outside the foreach loop.

protected void btnZip_Click(object sender, EventArgs e)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    string fileName = String.Empty;
    string ZipFileName = Server.MapPath(Path.Combine("TempFiles",Guid.NewGuid().ToString() + ".zip"));
    string local_path = tvDirTree.SelectedNode.Value.ToString();

    // what does this do?  
    local_path = "." + local_path.Substring(local_path.IndexOf("file_repository") - 1, 
        (local_path.Length - local_path.IndexOf("file_repository")) + 1).Replace("\\", "/");
            
    using (ZipFile zip = new ZipFile())
    {
        // Iterate through the Products.Rows property
        foreach (GridViewRow row in dgFiles.Rows)
        {
            // Access the CheckBox
            CheckBox cb = (CheckBox)row.FindControl("chkSelect");
            if (cb != null && cb.Checked)
            {
                fileName = (row.FindControl("lblFileName") as Label).Text;
                zip.AddFile(Server.MapPath(Path.Combine(local_path,fileName)), "");
                zip.AddFile(Server.MapPath(Path.Combine(local_path,"styleguide.docx")), "");
            }
        }                    

        zip.Save(ZipFileName);
    }
    
    Response.Clear();
    Response.BufferOutput = false;
    Response.ContentType = "application/zip";
    string archiveName = String.Format("archive-{0}.zip", DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
    Response.AppendHeader("Content-Disposition", "attachment; filename=" + archiveName);
    Response.WriteFile(ZipFileName);
    Response.Flush();
    Response.Close();

    // delete the temp file 
    if (File.Exists(ZipFileName))
        File.Delete(ZipFileName);
            
    sb.Append(String.Format("Folder {0} Zipped successfuly to File {1}.<br/>", local_path, ZipFileName));
    lbReport.Text = sb.ToString();

}

Also, you can drop HttpContext.Current.ApplicationInstance.CompleteRequest(); .  It should be unnecessary if you've called Response.Close().

In your code, I replaced string concatenation with calls to Path.Combine(), which is the recommended way to do things.  (Path is in the System.IO namespace)

Last thing - I don't know why you are doing the local_path string manipulation (See my comment in your code), and replacing backslashes with slashes.  It seems sort of convoluted. There's probably an easier way to do whatever it is you're doing, with static methods in the Path class.  And, in case you are doing the Replace("\\","/") for the benefit of DotNetZip - it's not necessary. 

Good luck

 

Jan 13, 2010 at 8:43 PM

That worked great!  Thanks Cheeso!!  I only had to make one small change and move the zip.AddFile for the style guide outside of the loop as well, so it is only added once...when it tried to add a second time it caused an error.  Thanks again for your help!!