1

I am able to zip files from a specific folder using ZipFile.CreateFromDirectory in the following test code (I only used this code to test how zipping works):

// Where the files are located
string strStartPath = txtTargetFolder.Text;

// Where the zip file will be placed
string strZipPath = @"C:\Users\smelmo\Desktop\testFinish\" + strFileNameRoot + "_" + txtDateRange1.Text.Replace(@"/", "_") + "_" + txtDateRange2.Text.Replace(@"/", "_") + ".zip";

ZipFile.CreateFromDirectory(strStartPath, strZipPath);

However, this zips together ALL of the contents in the folder. I am trying to zip together specific items in the folder using ZipArchive in the following code:

// Where the files are located
string strStartPath = txtTargetFolder.Text;

// Where the zip file will be placed
string strZipPath = @"C:\Users\smelmo\Desktop\testFinish\" + strFileNameRoot + "_" + txtDateRange1.Text.Replace(@"/", "_") + "_" + txtDateRange2.Text.Replace(@"/", "_") + ".zip";

using (ZipArchive archive = ZipFile.OpenRead(strStartPath))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        if (!(entry.FullName.EndsWith(".TIF", StringComparison.OrdinalIgnoreCase)))
        {
            entry.ExtractToFile(Path.Combine(strZipPath, entry.FullName));
         }
     }
 }

It is giving the error at ZipFile.OpenRead(strStartPath). Why am I able to access the exact folder in the first block of code but not the second? Or is there an easier way to search through a folder and only zip specific items?

smelmo
  • 75
  • 1
  • 10
  • Can you show us an example value contained in strZipPath? When the code runs, will that file exist at that location (prior to the code running), or is your expectation that the OpenRead call will create that file for you? – mjwills Jun 09 '17 at 14:12
  • @mjwills strZipPath will be a folder already created, which is on my desktop. Using a `FolderBrowserDialog`, it will obtain C:\Users\smelmo\Desktop\03, which has all of the files that I am sorting through. – smelmo Jun 09 '17 at 14:15

1 Answers1

2

You are utilizing the Zip libraries wrong

Effectively you are trying to open a directory as if it were a zip file, then loop over the contents of that directory (which again is actually a zip file) and then attempting to extract each member into a different zip file

Here is a working example of what you have described you are trying to do:

string strStartPath = @"PATH TO FILES TO PUT IN ZIP FILE";

string strZipPath = @"PATH TO ZIP FILE";

if (File.Exists(strZipPath))
    File.Delete(strZipPath);

using (ZipArchive archive = ZipFile.Open(strZipPath,  ZipArchiveMode.Create))
{
    foreach (FileInfo file in new DirectoryInfo(strStartPath).GetFiles())
    {
        if (!(file.FullName.EndsWith(".TIF", StringComparison.OrdinalIgnoreCase)))
        { 
            archive.CreateEntryFromFile(Path.Combine(file.Directory.ToString(), file.Name), file.Name);
        }
    }
}

This will take all the root level contents of a folder and put it in the zip file. You will need to implement your own way of getting subfolders and their contents recursively, but that is beyond the scope of this question.

EDIT: Here is a working example with proper folder recursion to select all files even in subdirectories

public void ZipFolder()
{
    string strStartPath = @"PATH TO FILES TO PUT IN ZIP FILE";

    string strZipPath = @"PATH TO ZIP FILE";

    if (File.Exists(strZipPath))
        File.Delete(strZipPath);

    using (ZipArchive archive = ZipFile.Open(strZipPath, ZipArchiveMode.Create))
    {
        foreach (FileInfo file in RecurseDirectory(strStartPath))
        {
            if (!(file.FullName.EndsWith(".TIF", StringComparison.OrdinalIgnoreCase)))
            {
                var destination = Path.Combine(file.DirectoryName, file.Name).Substring(strStartPath.Length + 1);
                archive.CreateEntryFromFile(Path.Combine(file.Directory.ToString(), file.Name), destination);
            }
        }
    }
}

public IEnumerable<FileInfo> RecurseDirectory(string path, List<FileInfo> currentData = null)
{
    if (currentData == null)
        currentData = new List<FileInfo>();   

    var directory = new DirectoryInfo(path);

    foreach (var file in directory.GetFiles())
        currentData.Add(file);

    foreach (var d in directory.GetDirectories())
        RecurseDirectory(d.FullName, currentData);
    return currentData;
}
Robert Petz
  • 2,718
  • 4
  • 23
  • 52
  • On a related note it appears that the exception you are getting is highly misleading - I got that a lot too for similar issues. It seems like if it has any internal exception come up it throws that access denied exception, even if it was caused from trying to open a folder as a zip file. Quite odd – Robert Petz Jun 09 '17 at 14:35
  • A few questions:What exactly is the if() statement doing? Why would it delete anything? Also, would I put my personal if() statement after the foreach() loop to go through and only zip specific items? – smelmo Jun 09 '17 at 14:40
  • the if statement was from when I was testing locally, but I left it in to show how you would handle that case. Basically you can only call `Create` or `Update` upon the new zip file - so if it exists already exists then `Create` throws an exception and if it doesn't `Update` throws an exception. For my own personal testing I opted to just create a new zip file every time, but how you implement that part of your logic is entirely up to your needs. I totally left out your provided if statement on accident, I'll add that in to my answer. – Robert Petz Jun 09 '17 at 14:46
  • This is working as needed. Will `FileInfo` also check for folders? That is working to pull particular files, but I also would need to get folders. I know that was not part of the question originally. Basically, `strStartPath` contains folders 0001,0002, etc and I am trying to zip THOSE folders together. I thought that `FileInfo` would pull those as well. – smelmo Jun 09 '17 at 15:05
  • @smelmo I went ahead and added an example using recursion so it'll grab subfolder files. It should be pretty explanatory from there if you need further changes to it in order to apply to your needs – Robert Petz Jun 09 '17 at 15:31
  • I don't need the subfolder files, I would want to zip those subfolders together. `strStartPath` contains tons of files. I am already creating subfolders based on certain criteria, such as date created, which then get placed in folders 0001, 0002, etc depending on the amount of files that meet said criteria. So if I have a lot of subfolders, I want to just zip those together. I am having trouble zipping those folders together now. – smelmo Jun 09 '17 at 15:41
  • @smelmo I don't mean to sound rude, but this is a Q and A site and not a place to ask others to write your code for you haha. I believe from what I have provided above you should have more than enough information to implement what it is you are trying to implement, but you will have to implement your own code for your specific needs and requirements yourself. From the sound of what you have described the above code should give you all the information you need to tweak it to your needs. – Robert Petz Jun 09 '17 at 15:43
  • 1
    No I completely understand, and I apologize if what I am asking is coming off that way. What you have provided is great and has helped me a lot. I have been searching for ways to zip folders together, but all that I am finding is ways to zip files. – smelmo Jun 09 '17 at 15:46
  • @smelmo - I think I see where your confusion is, and it got me too. In a Zip archive there are no such thing as folders, when you place the file in the archive using `CreateEntryFromFile` the first argument is the filepath you want to put into the archive and the second is the filename to use inside the archive *including it's path*. So if you have a file named '12345.jpg' and you want it in a folder called '0001' in your zip file, pass '0001\12345.jpg' to the second argument of `CreateEntryFromFile` – Robert Petz Jun 09 '17 at 15:56
  • So if there are no such thing as folders in a ZipArchive, I need to find another way to zip together subfolders within a folder? – smelmo Jun 09 '17 at 16:31
  • let me rephrase that - folders are fuax folders in a zip file. The relative file path can have a folder, but there is no 'folder' entry per se. If you need a file to exist in folder '0001', give it a file path of `0001\filename.tiff` and it will be shown as existing in folder '0001' by anything zip file viewer. You have full control over which files go into that "folder" by whatever logic you implement, and you can name that "folder" whatever you want. – Robert Petz Jun 09 '17 at 16:35