9

I have list of internet URLS I am trying to create a zip using Memorystream. The files are on s3 bucket however s3 sdk doesnt have any function to download folder as zip.

Avoiding to save it on server and delete those. The project is running on Ubuntu. I have tried getting the response as follows,

var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("MyClient", "1.0"));
var result = await httpClient.GetStreamAsync(names[0]);

However the ZipArchive class in .NET takes local files path and not memorystream

Note: I cannot use SharpZipLib since it is not supported by .NET Core.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Raveendra Patil
  • 91
  • 1
  • 1
  • 2

2 Answers2

18

However the ZipArchive class in .NET takes local files path and not memorystream

This is untrue, the ZipArchive class has overloads that accept Stream instances:

https://msdn.microsoft.com/en-us/library/hh158268(v=vs.110).aspx

Initializes a new instance of the ZipArchive class from the specified stream.

public ZipArchive(Stream stream)

(Documentation is for the full .NET Framework, but the .NET Core implementation has the same interface: https://github.com/dotnet/corefx/blob/master/src/System.IO.Compression/src/System/IO/Compression/ZipArchive.cs )

Like so:

class ItemToAdd {
    public String Name;
    public Stream Content;
}

List<ItemToAdd> itemsToAdd = GetItemsFromAmazonS3();

using( MemoryStream zipStream = new MemoryStream() ) {
    
    using( ZipArchive zip = new ZipArchive( zipStream, ZipArchiveMode.Create ) ) {
    
        foreach( ItemToAdd item in itemsToAdd ) {
        
            ZipArchiveEntry entry = zip.CreateEntry( item.Name );
            using( Stream entryStream = entry.Open() ) {
                
                item.Content.CopyTo( entryStream );
            }
        }

    }
    
    zipStream.Position = 0;

    // copy zipStream to output, or return it directly depending on your web framework
}
Dai
  • 141,631
  • 28
  • 261
  • 374
  • not sure if this changes the answer but your documentation link is for the full .net Framework not .net Core – Ronan Thibaudau Apr 07 '17 at 18:32
  • @RonanThibaudau Thank you for pointing that out - fortunately the DNX version has the same interface: https://github.com/dotnet/corefx/blob/master/src/System.IO.Compression/src/System/IO/Compression/ZipArchive.cs – Dai Apr 07 '17 at 18:43
  • @Dai Thanks I will try this. Thank you for your time – Raveendra Patil Apr 10 '17 at 07:37
  • 2
    There's an error when you create the ZipArchive with 'new ZipArchive()'. You need to specify the mode, for example 'new new ZipArchive(zipStream, ZipArchiveMode.Create)'. See https://stackoverflow.com/questions/33687425/central-directory-corrupt-error-in-ziparchive – MeanGreen Aug 08 '17 at 14:11
  • 2
    @MeanGreen I've updated my answer - sorry for the 3 year wait! – Dai Jan 21 '21 at 03:47
2

This is how xml Doc can be zipped and uploaded to aws S3, hope will help someone.

var stMarged = new System.IO.MemoryStream();
Doc.Save(stMarged);


stMarged.Position = 0;
using (MemoryStream zipStream = new MemoryStream())
{
    using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
    {
        ZipArchiveEntry entry = zip.CreateEntry("propertyFeed.xml");

        using (Stream entryStream = entry.Open())
        {
            stMarged.CopyTo(entryStream);
        }

        //Not the best way but the file is smaler 
        //ZipArchiveEntry entry1 = zip.CreateEntry("propertyFeed1.xml");
        //using (StreamWriter writer = new StreamWriter(entry1.Open()))
        //    writer.Write(Doc2.OuterXml);
    }

    zipStream.Position = 0;
    aa += UploadZipStreamToS3(zipStream);
}