ICSharpCode.SharpZipLib validate zip file
Asked Answered
P

2

8

Using ICSharpCode.SharpZipLib for C#, how can I validate that the file being passed is actually a valid zip file (not something that has been right clicked and renamed as .zip)?

[HttpPost]
        public ActionResult Upload(HttpPostedFileBase fileData)
        {
                if (fileData != null && fileData.ContentLength > 0)
                {
                    if (Path.GetExtension(fileData.FileName) == ".zip")
                    {
                        var zipFile = Server.MapPath("~/Content/uploads/" + Path.GetFileName(fileData.FileName));
                        fileData.SaveAs(zipFile);

                        FileStream fs = System.IO.File.OpenRead(zipFile);
                        ZipFile zf = new ZipFile(fs);

                        foreach (ZipEntry zipEntry in zf)
                        {
                            if (zipEntry.Name.EndsWith(".htm") || zipEntry.Name.EndsWith(".html"))
                            {
                                 return Json(new { success = true });                             
                            }
                        }
                        fs.Close();
                        fs.Dispose();
                        System.IO.File.Delete(zipFile);
                    }
                    else
                    {
                        var fileName = Server.MapPath("~/Content/uploads/" + Path.GetFileName(fileData.FileName));
                        fileData.SaveAs(fileName);                           
                        return Json(new { success = true });
                    }
                }                    
                return Json(new { success = false });

    }
Photoengraving answered 2/3, 2012 at 20:12 Comment(0)
S
18

You can use the ZipFile.TestArchive method. Here is how it is declared in SharpZipLib:

/// <summary>
/// Test an archive for integrity/validity
/// </summary>
/// <param name="testData">Perform low level data Crc check</param>
/// <returns>true if all tests pass, false otherwise</returns>
/// <remarks>Testing will terminate on the first error found.</remarks>
public bool TestArchive(bool testData)
{
    return TestArchive(testData, TestStrategy.FindFirstError, null);
}

Usage example:

ZipFile zipFile = new ZipFile("archive.zip");
Console.WriteLine("Archive validation result: {0}", zipFile.TestArchive(true));
Scalable answered 2/3, 2012 at 20:23 Comment(3)
does this verify the entire archive? I have a ~1GB password protected zip file that I am able to enumerate through its entries but when I perform the extraction it crashes at ~56%. Can I just test it before beginning to extract it?Neusatz
Does this also check for Zip Bombs. Means the reported size of the packed file is not the same size when you unzip the file.Telecommunication
Sorry to revive this, but the example you gave fails at the new ZipFile() call if the file isn't a valid archive (for example a .txt file renamed to .zip, similar to what OP specified). It throws an exception with the message Cannot find central directory.Lunular
M
0

Be careful with this one. It created an IOAccess error on the file for me when I immediately attempted to rename, I had to add a using statement:

public static bool ValidateZipFile(string fileToTest)
{
    bool result;
    //Added using statement to fix IOAccess Blocking
    using (ICSharpCode.SharpZipLib.Zip.ZipFile zip = new ICSharpCode.SharpZipLib.Zip.ZipFile(fileToTest))
    {
        result = zip.TestArchive(true, TestStrategy.FindFirstError, null);
    }
    return result;
}
Mayfield answered 28/4, 2016 at 22:29 Comment(1)
If I use the code exactly like this in SharpZipLib 0.86.0, I get a ZipException ("Cannot find central directory") thrown in the ZipFile constructor, because the constructor already tries to access the ZIP file. However, you can not use TestArchive without creating an instance.Sebbie

© 2022 - 2024 — McMap. All rights reserved.