C# UnauthorizedAccessException при использовании ZipArchive, но не ZipFile

Я могу заархивировать файлы из определенной папки, используя ZipFile.CreateFromDirectory в следующем тестовом коде (я использовал этот код только для проверки работы архива):

// 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);

Однако это объединяет ВСЕ содержимое папки. Я пытаюсь сжать определенные элементы в папке, используя ZipArchive в следующем коде:

// 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));
         }
     }
 }

Это дает ошибку в ZipFile.OpenRead(strStartPath), Почему я могу получить доступ к точной папке в первом блоке кода, но не во втором? Или есть более простой способ поиска по папке и архивирования только определенных элементов?

1 ответ

Решение

Вы используете библиотеки Zip неправильно

Фактически вы пытаетесь открыть каталог, как если бы это был zip-файл, затем зациклите содержимое этого каталога (который опять-таки фактически является zip-файлом), а затем пытаетесь извлечь каждого члена в отдельный zip-файл.

Вот рабочий пример того, что вы описали, что вы пытаетесь сделать:

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);
        }
    }
}

Это возьмет все содержимое корневого уровня папки и поместит его в zip-файл. Вам нужно будет реализовать свой собственный способ получения подпапок и их содержимого рекурсивно, но это выходит за рамки этого вопроса.

РЕДАКТИРОВАТЬ: Вот рабочий пример с правильной рекурсией папки для выбора всех файлов даже в подкаталогах

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;
}
Другие вопросы по тегам