1

Create Compressed Folder

I would like to zip a folder, I tried to write code that should do this, but I am getting an error that the folder is empty :

  1. Create the empty zip file.
  2. It does not allow me to extract the files from the zip file (It tells me that, in fact, that the folder is empty).

MainPage.xaml:

<Grid>
   <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
       <StackPanel Orientation="Horizontal" Margin="5">
           <Button x:Name="BtnChooseFolder" Click="BtnChooseFolder_Click" Content="Choose Folder" Margin="5"/>
           <TextBlock Text="Folder to Zip: " VerticalAlignment="Center"/>
           <TextBlock x:Name="TxbFolderToZip" VerticalAlignment="Center"/>
       </StackPanel>
       <StackPanel Orientation="Horizontal" Margin="5">
           <Button x:Name="BtnChooseDestination" Click="BtnChooseDestination_Click" Content="Choose Destination" Margin="5"/>
           <TextBlock Text="Zip Folder: " VerticalAlignment="Center"/>
           <TextBlock x:Name="TxbZipFolder" VerticalAlignment="Center"/>
       </StackPanel>
       <StackPanel Orientation="Horizontal">
           <Button x:Name="BtnZip" Click="BtnZip_Click" Content="Zippa" Margin="10"/>
           <TextBlock x:Name="TxbPercentage" VerticalAlignment="Center"/>
       </StackPanel>
   </StackPanel>
</Grid>

MainPage.xaml.cs:

string FolderPathOne = string.Empty;
string FoldeDestinationOne = string.Empty;

StorageFolder FolderPath;
StorageFolder DestinationPath;

public MainPage()
{
    this.InitializeComponent();
}

private async void BtnChooseFolder_Click(object sender, RoutedEventArgs e)
{
    FolderPicker FolderPickFol = new FolderPicker();
    FolderPickFol.SuggestedStartLocation = PickerLocationId.Desktop;
    FolderPickFol.FileTypeFilter.Add("*");
    StorageFolder SelectFolderToZipa = await FolderPickFol.PickSingleFolderAsync();
    StorageApplicationPermissions.FutureAccessList.AddOrReplace("PickedFolder", SelectFolderToZipa);
    FolderPath = SelectFolderToZipa;
    FolderPathOne = SelectFolderToZipa.Path;
    TxbFolderToZip.Text = FolderPathOne;
}

private async void BtnChooseDestination_Click(object sender, RoutedEventArgs e)
{
    FolderPicker FolderPickFol = new FolderPicker();
    FolderPickFol.SuggestedStartLocation = PickerLocationId.Desktop;
    FolderPickFol.FileTypeFilter.Add("*");
    StorageFolder SelectFolderToZipa = await FolderPickFol.PickSingleFolderAsync();
    StorageApplicationPermissions.FutureAccessList.AddOrReplace("PickedDestination", SelectFolderToZipa);
    DestinationPath = SelectFolderToZipa;
    FoldeDestinationOne = SelectFolderToZipa.Path;
    TxbZipFolder.Text = FoldeDestinationOne;
}

private async void BtnZip_Click(object sender, RoutedEventArgs e)
{
    StorageFile zipFile = await DestinationPath.CreateFileAsync("ZipFolderTest.zip", CreationCollisionOption.ReplaceExisting);
    Stream zipToCreate = await zipFile.OpenStreamForWriteAsync();
    ZipArchive archive = new ZipArchive(zipToCreate, ZipArchiveMode.Update);

    await ZipFolderContents(FolderPath, archive, FolderPath.Path);
}

private async Task ZipFolderContents(StorageFolder sourceFolder, ZipArchive archive, string sourceFolderPath)
{
    IReadOnlyList<StorageFile> files = await sourceFolder.GetFilesAsync();
    foreach (StorageFile file in files)
    {
        ZipArchiveEntry readmeEntry = archive.CreateEntry(file.Path.Remove(0, sourceFolderPath.Length));
        byte[] buffer = WindowsRuntimeBufferExtensions.ToArray(await FileIO.ReadBufferAsync(file));
        using (Stream entryStream = readmeEntry.Open())
        {
            await entryStream.WriteAsync(buffer, 0, buffer.Length);
        }
    }
}

Although there is writing in the stream, it creates the empty and inaccessible file.

Thanks in advance!

Muhammad Touseef
  • 4,357
  • 4
  • 31
  • 75
Jimmy
  • 45
  • 5

1 Answers1

0

For your scenario, you could use ZipFile.CreateFromDirectory method to compress folder directly.

string DestinationFolderPath = string.Empty;
string SourceFolderPath = string.Empty;

StorageFolder SourceFolder;
StorageFolder DestinationFolder;

private async void BtnChooseFolder_Click(object sender, RoutedEventArgs e)
{
    FolderPicker FolderPickFol = new FolderPicker();
    FolderPickFol.SuggestedStartLocation = PickerLocationId.Desktop;
    FolderPickFol.FileTypeFilter.Add("*");
    Windows.Storage.StorageFolder SelectFolderToZipa = await FolderPickFol.PickSingleFolderAsync();
    StorageApplicationPermissions.FutureAccessList.AddOrReplace("PickedFolder", SelectFolderToZipa);
    SourceFolder = SelectFolderToZipa;
    SourceFolderPath = SelectFolderToZipa.Path;
    TxbFolderToZip.Text = SourceFolderPath;
}

private async void BtnChooseDestination_Click(object sender, RoutedEventArgs e)
{
    FolderPicker FolderPickFol = new FolderPicker();
    FolderPickFol.SuggestedStartLocation = PickerLocationId.Desktop;
    FolderPickFol.FileTypeFilter.Add("*");
    StorageFolder SelectFolderToZipa = await FolderPickFol.PickSingleFolderAsync();
    StorageApplicationPermissions.FutureAccessList.AddOrReplace("PickedDestination", SelectFolderToZipa);
    DestinationFolder = SelectFolderToZipa;
    DestinationFolderPath = SelectFolderToZipa.Path;
    TxbZipFolder.Text = DestinationFolderPath;
}

private async void BtnZip_Click(object sender, RoutedEventArgs e)
{

    if (SourceFolder != null)
    {

        StorageApplicationPermissions.FutureAccessList.AddOrReplace("PickedFolderToken", SourceFolder);
        await Task.Run(() =>
        {
            try
            {

                System.IO.Compression.ZipFile.CreateFromDirectory(SourceFolderPath, $"{DestinationFolderPath}\\{SourceFolder.Name}.zip");

            }
            catch (Exception w)
            {

            }
        });

    }
}

For this method, you just pass the source folder path and the destination zip file two parameters.

ZipFile.CreateFromDirectory(SourceFolderPath, $"{DestinationFolderPath}\\{SourceFolder.Name}.zip");

The above code is edited base on your post, you could use it directly in your project.

Update

Derive from this case.

This System.ArgumentException is thrown from the WindowsRuntimeBufferExtensions ToArray method, which expects that the IBuffer's size is larger than 0.

So I replace it with the follow method

private async Task ZipFolderContentsHelper(StorageFolder sourceFolder, ZipArchive archive, string sourceFolderPath)
{
    IReadOnlyList<StorageFile> files = await sourceFolder.GetFilesAsync();

    foreach (StorageFile file in files)
    {
        var path = file.Path.Remove(0, sourceFolderPath.Length);
        ZipArchiveEntry readmeEntry = archive.CreateEntry(file.Path.Remove(0, sourceFolderPath.Length));
        ulong fileSize = (await file.GetBasicPropertiesAsync()).Size;
        byte[] buffer = fileSize > 0 ? (await FileIO.ReadBufferAsync(file)).ToArray()
        : new byte[0];


        using (Stream entryStream = readmeEntry.Open())
        {
            await entryStream.WriteAsync(buffer, 0, buffer.Length);
        }
    }

    IReadOnlyList<StorageFolder> subFolders = await sourceFolder.GetFoldersAsync();

    if (subFolders.Count() == 0)
    {
        return;
    }

    foreach (StorageFolder subfolder in subFolders)
    {
        await ZipFolderContentsHelper(subfolder, archive, sourceFolderPath);
    }
}

This is code sample that you could use directly.

Nico Zhu
  • 32,367
  • 2
  • 15
  • 36
  • I knew this method ... I wanted to use the stream, as in my example, because I wanted the completed bytes to display the percentage. – Jimmy Sep 13 '18 at 10:03
  • Have you check this [reply](https://stackoverflow.com/a/36738028/7254781). – Nico Zhu Sep 13 '18 at 10:18
  • In this example, there is how to extract them, but if I try to adapt it to make them compress it is not clear how to do it. – Jimmy Sep 13 '18 at 10:40
  • @Jimmy , I solved issue and update reply. for better understanding, I uploaded the code sample. – Nico Zhu Sep 14 '18 at 09:09
  • Thanks...! Work perfectly .. But how can the percentage be calculated? – Jimmy Sep 14 '18 at 13:12
  • @NicoZhu-MSFT, the result zip file doesn't contain hidden files, hidden folders, .lnk, .url files of the source, while zipping the other files correctly. Any solution? – Mg Bhadurudeen May 15 '21 at 18:20