ZipFile Extension for CSHTML5 (Ionic.Zip DotNetZip-like)

JS-Support @Userware
Site Admin
Posts: 1142
Joined: Tue Apr 08, 2014 3:42 pm

ZipFile Extension for CSHTML5 (Ionic.Zip DotNetZip-like)

Postby JS-Support @Userware » Fri Mar 04, 2016 10:07 am

Dear CSHTML5 users,

I am pleased to inform you of the release of the ZipFile Extension for CSHTML5.


It adds the ability to create ZIP files and to read ZIP files. It attempts to mimic the API of Ionic.Zip (DotNetZip) so as to make it easier to migrate existing C# projects to CSHTML5.

You can use it in conjunction with the FileSaver Extension to save the ZIP files to the disk. You can also use it in conjunction with the FileOpenDialog Extension to read a ZIP file from the disk.


It requires CSHTML5 v1.0 Beta 7.2 or newer.

UPDATE (July 20, 2017): Added support for compressing and decompressing byte arrays.

To use, simply add a new class named "ZipFile.cs" to your project, and copy/paste the following code:

Code: Select all

using CSHTML5;
using System;
using System.Threading.Tasks;

//------------------------------------
// This is an extension for C#/XAML for HTML5 (www.cshtml5.com)
//
// It requires Beta 7.2 or newer.
//
// It adds the ability to create ZIP files and to read ZIP files.
// It attempts to mimic the API of Ionic.Zip (DotNetZip) so as to
// make it easier to migrate existing C# projects to CSHTML5.
//
// You can use it in conjunction with the FileSaver Extension
// to save the ZIP files to the disk. You can also use it in
// conjunction with the FileOpenDialog Extension to read a ZIP
// file from the disk.
//
// The extension works by wrapping the JavaScript "JSZip.js"
// library into a C#/XAML class for consumption by CSHTML5-based
// apps. The "JSZip.js" library source code can be found at:
// https://stuk.github.io/jszip/
//
// This extension is licensed under the open-source MIT license:
// https://opensource.org/licenses/MIT
//
// Copyright 2017 Userware / CSHTML5
//------------------------------------

namespace Ionic.Zip
{
    public class ZipFile : IDisposable
    {
        static bool JSLibraryWasLoaded;

        object _referenceToJavaScriptZipInstance;

        public async Task AddFile(string fileName, string fileContent)
        {
            await LoadJSLibrary();

            Initialize();

            Interop.ExecuteJavaScript(@"$0.file($1, $2)", _referenceToJavaScriptZipInstance, fileName, fileContent);
        }

        public async Task AddFile(string fileName, Byte[] fileContent)
        {
            await LoadJSLibrary();

            Initialize();

            if (!CSHTML5.Interop.IsRunningInTheSimulator)
            {
                Interop.ExecuteJavaScript(@"$0.file($1, $2)", _referenceToJavaScriptZipInstance, fileName, fileContent);
            }
            else
            {
                int length = fileContent.Length;
                var array = Interop.ExecuteJavaScript("new Uint8Array($0)", length);
                for(int i = 0; i< length; ++i)
                {
                    Interop.ExecuteJavaScript("$0[$1] = $2", array, i, fileContent[i]);
                }
                Interop.ExecuteJavaScript(@"$0.file($1, $2)", _referenceToJavaScriptZipInstance, fileName, array);
            }
        }

        public async Task<object> SaveToJavaScriptBlob()
        {
            await LoadJSLibrary();

            Initialize();

            object blob = Interop.ExecuteJavaScript(@"$0.generate({type:""blob""})", _referenceToJavaScriptZipInstance);

            return blob;
        }

        public void Dispose()
        {
        }

        static async Task LoadJSLibrary()
        {
            if (!JSLibraryWasLoaded)
            {
                await Interop.LoadJavaScriptFile(@"https://cdnjs.cloudflare.com/ajax/libs/jszip/2.5.0/jszip.min.js");
                JSLibraryWasLoaded = true;
            }
        }

        void Initialize()
        {
            if (_referenceToJavaScriptZipInstance == null)
                _referenceToJavaScriptZipInstance = Interop.ExecuteJavaScript("new JSZip()");
        }

        public static async Task<ZipFile> Read(object javaScriptBlob)
        {
            await LoadJSLibrary();

            var zipFile = new ZipFile();

            zipFile._referenceToJavaScriptZipInstance = Interop.ExecuteJavaScript("new JSZip($0)", javaScriptBlob);

            return zipFile;
        }

        public ZipEntry this[string fileName]
        {
            get
            {
                var fileContainedInZipFile = Interop.ExecuteJavaScript(@"$0.files[$1]", _referenceToJavaScriptZipInstance, fileName);
                var zipEntry = new ZipEntry(fileContainedInZipFile);
                return zipEntry;
            }
        }
    }


    public class ZipEntry
    {
        object _referenceToJSZipFile;

        public ZipEntry(object referenceToJSZipFile)
        {
            _referenceToJSZipFile = referenceToJSZipFile;
        }

        public string ExtractToString()
        {
            return (string)Interop.ExecuteJavaScript(@"$0.asText()", _referenceToJSZipFile);
        }

        public Byte[] ExtractToByteArray()
        {
            return (Byte[])Interop.ExecuteJavaScript(@"$0.asUint8Array()", _referenceToJSZipFile);

        }

        public object ExtractToJavaScriptArrayBuffer()
        {
            return Interop.ExecuteJavaScript(@"$0.asArrayBuffer()", _referenceToJSZipFile);
        }

        public string FileName
        {
            get
            {
                return (string)Interop.ExecuteJavaScript(@"$0.name", _referenceToJSZipFile);
            }
        }
    }
}



The extension works by wrapping the JavaScript "JSZip.js" library into a C#/XAML class for consumption by CSHTML5-based apps. The "JSZip.js" library source code can be found at: https://stuk.github.io/jszip/


You can test the code by calling the following C# code.

- To create a ZIP file that contains a text file (note: this sample code requires the FileSaver Extension as well):

Code: Select all

using (ZipFile zipFile = new ZipFile())
{
    await zipFile.AddFile("MyTestFileInsideTheZIP.txt", "Hello World");
    var jsBlob = await zipFile.SaveToJavaScriptBlob();
    await FileSaver.SaveJavaScriptBlobToFile(jsBlob, "MyTestFile.zip");
}


- To read back the ZIP file and read the text file that is contained inside it (note: this sample code requires the OpenFileDialog as well):
XAML code:

Code: Select all

<Page
    ...
    xmlns:extensions="using:CSHTML5.Extensions.FileOpenDialog"
    ...
    >
    <Canvas>
        <extensions:ControlForDisplayingTheFileOpenDialog FileOpened="OnFileOpened" Filter="*.zip"/>
    </Canvas>
</Page>

C# code:

Code: Select all

async void OnFileOpened(object sender, FileOpenedEventArgs e)
{
    var javaScriptBlob = e.JavaScriptBlob;
    ZipFile zipFile = await ZipFile.Read(javaScriptBlob);
    ZipEntry entry = zipFile["MyTestFileInsideTheZIP.txt"];
    string content = entry.ExtractToString();
    MessageBox.Show(content);
}


Regards,
JS-Support

JS-Support @Userware
Site Admin
Posts: 1142
Joined: Tue Apr 08, 2014 3:42 pm

Re: ZipFile Extension for CSHTML5 (Ionic.Zip DotNetZip-like)

Postby JS-Support @Userware » Thu Jul 20, 2017 3:23 am

UPDATE: The ZipFile extension has been updated today with the following features:
- Support for compressing byte arrays
- Support for decompressing byte arrays

Regards,
JS-Support.


Return to “Extensions and Plugins for CSHTML5”

Who is online

Users browsing this forum: No registered users and 1 guest