8

I am writing a REST API which will take in a JSON request object. The request object will have to be serialized to a file in JSON format; the file has to be compressed into a zip file and the ZIP file has to be posted to another service, for which I would have to deserialize the ZIP file. All this because the service I have to call expects me to post data as ZIP file. I am trying to see if I can avoid disk IO. Is there a way to directly convert the object into a byte array representing ZIP content in-memory instead of all the above steps?

Note : I'd prefer accomplishing this using .net framework libraries (as against external libraries)

Aadith Ramia
  • 10,005
  • 19
  • 67
  • 86

4 Answers4

14

Yes, it is possible to create a zip file completely on memory, here is an example using SharpZip Library (Update: A sample using ZipArchive added at the end):

public static void Main()
{
    var fileContent = Encoding.UTF8.GetBytes(
        @"{
            ""fruit"":""apple"",
            ""taste"":""yummy""
          }"
        );


    var zipStream = new MemoryStream();
    var zip = new ZipOutputStream(zipStream);

    AddEntry("file0.json", fileContent, zip); //first file
    AddEntry("file1.json", fileContent, zip); //second file (with same content)

    zip.Close();

    //only for testing to see if the zip file is valid!
    File.WriteAllBytes("test.zip", zipStream.ToArray());
}

private static void AddEntry(string fileName, byte[] fileContent, ZipOutputStream zip)
{
    var zipEntry = new ZipEntry(fileName) {DateTime = DateTime.Now, Size = fileContent.Length};
    zip.PutNextEntry(zipEntry);
    zip.Write(fileContent, 0, fileContent.Length);
    zip.CloseEntry();
}

You can obtain SharpZip using Nuget command PM> Install-Package SharpZipLib

Update:

Note : I'd prefer accomplishing this using .net framework libraries (as against external libraries)

Here is an example using Built-in ZipArchive from System.IO.Compression.Dll

public static void Main()
{
    var fileContent = Encoding.UTF8.GetBytes(
        @"{
            ""fruit"":""apple"",
            ""taste"":""yummy""
          }"
        );

    var zipContent = new MemoryStream();
    var archive = new ZipArchive(zipContent, ZipArchiveMode.Create);

    AddEntry("file1.json",fileContent,archive);
    AddEntry("file2.json",fileContent,archive); //second file (same content)

    archive.Dispose();

    File.WriteAllBytes("testa.zip",zipContent.ToArray());
}


private static void AddEntry(string fileName, byte[] fileContent,ZipArchive archive)
{
    var entry = archive.CreateEntry(fileName);
    using (var stream = entry.Open())
        stream.Write(fileContent, 0, fileContent.Length);

}
Community
  • 1
  • 1
user3473830
  • 7,165
  • 5
  • 36
  • 52
4

You could use the GZipStream class along with MemoryStream.

A quick example:

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

//Put JSON into a MemoryStream
var theJson = "Your JSON Here";
var jsonStream = new MemoryStream();
var jsonStreamWriter = new StreamWriter(jsonStream);
jsonStreamWriter.Write(theJson);
jsonStreamWriter.Flush();

//Reset stream so it points to the beginning of the JSON
jsonStream.Seek(0, System.IO.SeekOrigin.Begin);

//Create stream to hold your zipped JSON
var zippedStream = new MemoryStream();

//Zip JSON and put it in zippedStream via compressionStream.
var compressionStream = new GZipStream(zippedStream, CompressionLevel.Optimal);
jsonStream.CopyTo(compressionStream);

//Reset zipped stream to point at the beginning of data
zippedStream.Seek(0, SeekOrigin.Begin);

//Get ByteArray with zipped JSON
var zippedJsonBytes = zippedStream.ToArray();
Yogster
  • 884
  • 1
  • 7
  • 27
  • When I try this, I get a 0-size array for zippedJsonBytes. Looks like theres a minor snag somewhere..could you pls help me out – Aadith Ramia Dec 15 '14 at 12:25
  • If I'm not mistaken, OP needs to create a `Zip` container, I'm afraid the proposed solution only compress data with Gzip algorithm and does not conform Zip container format. – user3473830 Dec 15 '14 at 12:26
  • Thanks @user3473830 ..That was going to be my other question..whats the difference between zip and gzip? – Aadith Ramia Dec 15 '14 at 12:28
  • @Aadith, my bad, I forgot to call jsonStreamWriter.Flush(); I have edited the example. – Yogster Dec 15 '14 at 12:30
  • 1
    @Aadith, if what you need is a whole zip archive (as opposed to Zipped data) then you can use the ZipArchive class as suggested below. There is an example in MSDN using FileStreams, but you could also use MemoryStreams as in my example. – Yogster Dec 15 '14 at 12:33
  • 1
    @Aadith, http://stackoverflow.com/questions/20762094/how-are-zlib-gzip-and-zip-related-what-are-is-common-and-how-are-they-differen – user3473830 Dec 15 '14 at 12:49
2

You should try the ZipArchive Class streaming to a MemoryStream Class

A. Rama
  • 903
  • 8
  • 18
0

Yes. You can return it as a binary stream. Depending on the language, you can use special libraries. You will also need libraries on the client.

ACV
  • 9,964
  • 5
  • 76
  • 81