3

I have a web services that returns a list of files. Something like this:

public FileModel(){
  string FileName {get;set;}
  byte[] FileStream {get;set;}
  string FileType {get;set;} 
}

My Service would return:

  List<FileModel> files;

I have to return this list to browser, so I need to compress these files into a zip folder.

However, I cant figure out how to do this, as .NET ZipArchive CreateFromDirectory is requiring me to provide a directory where the file to be zipped are. But I don't have a directory, I just have this list. How can I covert this list to a zipped folder.

Mark
  • 4,773
  • 8
  • 53
  • 91
  • 2
    What do you mean by *zip method*? All the constructors of the [ZipArchive](https://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive(v=vs.110).aspx) class accept `Stream`. – Ivan Stoev Apr 20 '16 at 18:46
  • `I have to return this list to browser,` No you can return filename,filetype and filesize to the browser. When user actually requests a specific file, you can return it compressed.... – Eser Apr 20 '16 at 18:51
  • @Eser, No, I actually need to return a zipped folder of the files to the browser/user. – Mark Apr 20 '16 at 19:07
  • 1
    Iconic's DotNetZip (Freeware) allows you to pass a byte[] to create a zip file. I don't know of anything that will let you pass a List though. – Kevin Apr 20 '16 at 19:11
  • It also lets you pass a stream or byte[] to the method for creating a file within the zip file. See if your library's CreateEntry method has an override that accepts a stream, if so create a MemoryStream from the byte[] and pass in the stream. – Kevin Apr 20 '16 at 19:13
  • `CreateEntry` parameter is just the logical name. Then you should call [ZipArchiveEntry.Open](https://msdn.microsoft.com/en-us/library/system.io.compression.ziparchiveentry.open(v=vs.110).aspx) to get a stream and write your `byte[]` data to it. – Ivan Stoev Apr 20 '16 at 19:16
  • The accepted answer didn't work for me. I used this instead: https://stackoverflow.com/questions/48927574/create-zip-file-in-memory-from-bytes-text-with-arbitrary-encoding – John Gilmer Apr 26 '20 at 17:42

1 Answers1

4

Given

public FileModel(){
    string FileName {get;set;}
    byte[] FileStream {get;set;}
    string FileType {get;set;} 
}

The following was written to create a zip file

static class FileModelCompression {

    public static Stream Compress(this IEnumerable<FileModel> files) {
        if (files.Any()) {
            var ms = new MemoryStream();
            using(var archive = new ZipArchive(ms, ZipArchiveMode.Create, leaveOpen: true)) {
                foreach (var file in files) {
                    var entry = archive.add(file);
                }
            }// disposal of archive will force data to be written to memory stream.
            ms.Position = 0; //reset memory stream position.
            return ms;
        }
        return null;
    }

    private static ZipArchiveEntry add(this ZipArchive archive, FileModel file) {
        var entry = archive.CreateEntry(file.FileName, CompressionLevel.Fastest);
        using (var stream = entry.Open()) {
            file.FileStream.CopyTo(stream);
        }
        return entry;
    }
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • If we use your code, we are able to create this file and see the files in the zip but: When we try to extract the zip, we have an error complaining about an unexpected end of archive. – ProblemAnswerQue May 08 '17 at 14:33