1

I am developing UWP and Windows phone 8.1 in the same solution.

On both projects I need a functionality of compressing a whole folder to one gzip file (in order to send it to server).

Libraries I've tried and encountered issues with:

SharpZipLib - uses System.IClonable which I cannot referance in my PCL project

DotNetZip - Not Suporting PCL/UWP

System.IO.Compression - Work only with Stream, cannot compress whole folder

I can split the implementation for each platform (although it is not perfect) but I still didn't found something that can be used in UWP.

Any help will be appriciated

Pavel Durov
  • 1,287
  • 2
  • 13
  • 28
  • Can you explain, a bit more in detail, why you could not use IO.Compression? I've never had issues with using CreateFromDirectory in the ZipFile libraries, but I'm also not writing a UWP or WP application, so maybe that's the issue? – gravity May 16 '16 at 14:28
  • Oh, must have missed CreateFromDirectory :) I'll try – Pavel Durov May 16 '16 at 14:42
  • Apperenlty I just dont have ZipFile in IO.Compression namespace, I have : ZipArchive, GZipStream, DeflateStream - they all works only with Stream... – Pavel Durov May 16 '16 at 14:48
  • I'm still not clear, UWP/WP apps can't use Streams? – gravity May 16 '16 at 14:49
  • They can, but how do you open a stream to a folder? – Pavel Durov May 16 '16 at 15:33

2 Answers2

0

Ok, so I found this project called SharpZipLib.Portable which is also an open source Github : https://github.com/ygrenier/SharpZipLib.Portable

Really nice :)

Pavel Durov
  • 1,287
  • 2
  • 13
  • 28
-1

Working on a UWP library you will have to use the Stream subsystem of the System.IO.Compression. There are many such limitations when you need a PCL version of .NET Framework. Live with that.

In your context that is not much of a trouble.

The required usings are:

using System;
using System.IO;
using System.IO.Compression;

Then the methods...

    private void CreateArchive(string iArchiveRoot)
    {
        using (MemoryStream outputStream = new MemoryStream())
        {
            using (ZipArchive archive = new ZipArchive(outputStream, ZipArchiveMode.Create, true))
            {
                //Pick all the files you need in the archive.
                string[] files = Directory.GetFiles(iArchiveRoot, "*", SearchOption.AllDirectories);

                foreach (string filePath in files)
                {
                    FileAppend(iArchiveRoot, filePath, archive);
                }
            }
        }
    }

    private void FileAppend(
        string iArchiveRootPath,
        string iFileAbsolutePath,
        ZipArchive iArchive)
    {
        //Has to return something like "dir1/dir2/part1.txt".
        string fileRelativePath = MakeRelativePath(iFileAbsolutePath, iArchiveRootPath);

        ZipArchiveEntry clsEntry = iArchive.CreateEntry(fileRelativePath, CompressionLevel.Optimal);
        Stream entryData = clsEntry.Open();

        //Write the file data to the ZipArchiveEntry.
        entryData.Write(...);
    }

    //http://stackoverflow.com/questions/275689/how-to-get-relative-path-from-absolute-path
    private string MakeRelativePath(
        string fromPath, 
        string toPath)
    {
        if (String.IsNullOrEmpty(fromPath)) throw new ArgumentNullException("fromPath");
        if (String.IsNullOrEmpty(toPath))   throw new ArgumentNullException("toPath");

        Uri fromUri = new Uri(fromPath);
        Uri toUri = new Uri(toPath);

        if (fromUri.Scheme != toUri.Scheme) { return toPath; } // path can't be made relative.

        Uri relativeUri = fromUri.MakeRelativeUri(toUri);
        String relativePath = Uri.UnescapeDataString(relativeUri.ToString());

        if (toUri.Scheme.Equals("file", StringComparison.OrdinalIgnoreCase))
        {
            relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
        }

        return relativePath;
    }
Zverev Evgeniy
  • 3,643
  • 25
  • 42
  • I've tried to use something similar, but it didn't created me a regular gzip file (which I can uzip on Linux server for instance) as is. Did you managed to create a gzip formatted file which will be unzpped as a folder with the files you appended to the Stream (clsEntry)? – Pavel Durov May 16 '16 at 15:36
  • I was able to recompile the DotNetZip (https://dotnetzip.codeplex.com/) as PCL for Windows 8.1/Windows Phone 8.1 without big problems, took about an hour, did not try that yet though. The most of the job I had to do is to replace the file system calls. – Zverev Evgeniy May 16 '16 at 17:43