How to create an archive stream from IFormFileCollection - c#

I am receiving a IFormFileCollection and I was wondering how can I archive this collection into a zip/rar/whatever archive file, and send this archive as a stream somewhere else to be stored?
I want to work only in memory via Stream (s) since I will send it over HTTP later on.
class ArchiveService {
public Stream ArchiveFiles(string archiveName, IEnumerable<IFormFile> files) {
using MemoryStream stream = new MemoryStream();
using (System.IO.Compression.ZipArchive archive = ZipFile.Open([in memory!], ZipArchiveMode.Create)) {
foreach (var file in files) {
archive.CreateEntry(file.FileName, CompressionLevel.Fastest);
}
//something like -> archive.CopyTo(stream);
}
return stream;
}
}

Create an archive in memory and traverse the collection, adding the files to the archive.
The returned stream will contain the files compressed into the archive.
You can then do as you wish with the stream
public class ArchiveService {
public Stream ArchiveFiles(IEnumerable<IFormFile> files) {
MemoryStream stream = new MemoryStream();
using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: true)) {
foreach (IFormFile file in files) {
var entry = archive.CreateEntry(file.FileName, CompressionLevel.Fastest);
using (Stream target = entry.Open()) {
file.CopyTo(target);
}
}
}
stream.Position = 0;
return stream;
}
public async Task<Stream> ArchiveFilesAsync(IEnumerable<IFormFile> files) {
MemoryStream stream = new MemoryStream();
using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: true)) {
foreach (IFormFile file in files) {
var entry = archive.CreateEntry(file.FileName, CompressionLevel.Fastest);
using (Stream target = entry.Open()) {
await file.OpenReadStream().CopyToAsync(target);
}
}
}
stream.Position = 0;
return stream;
}
}

Related

Creating Zip file with multiple entries in C# .net

I created the functionality to get documents from blob storage and then add them to a zip file for download.
[HttpPost]
public FileContentResult DownloadDocumentsByDocIDZIP(List<int> documentIDs)
{
List<Document> docs = new List<Document>();
foreach (int doc in documentIDs)
{
if (doc != 0)
{
Document document = documentService.GetDocumentByID(doc, false);
docs.Add(document);
}
}
MemoryStream outms = new MemoryStream();
using (ZipArchive zar = new ZipArchive(outms, ZipArchiveMode.Create, false))
{
foreach (Document docu in docs)
{
if (docu != null)
{
byte[] documentdata = documentService.DownloadDocumentData(docu.DocumentID);
string name = docu.DocumentNiceName ?? docu.DocumentFileName;
byte[] unzipped = documentdata;
ZipArchiveEntry entry = zar.CreateEntry(name);
Stream str = entry.Open();
MemoryStream ms = new MemoryStream(unzipped);
ms.CopyTo(str);
}
}
outms.Seek(0, SeekOrigin.Begin);
}
var outdata = outms.ToArray();
var result = File(outdata, "application/zip", "documents.zip");
return result;
}
When I hit the function via ajax, It fails at
ZipArchiveEntry entry = zar.CreateEntry(name);
I'm given the exception,
System.IO.IOException: 'Entries cannot be created while previously created entries are still open.'
So I added str.close()
using (ZipArchive zar = new ZipArchive(outms, ZipArchiveMode.Create, false))
{
foreach (Document docu in docs)
{
if (docu != null)
{
byte[] documentdata = documentService.DownloadDocumentData(docu.DocumentID);
string name = docu.DocumentNiceName ?? docu.DocumentFileName;
byte[] unzipped = documentdata;
ZipArchiveEntry entry = zar.CreateEntry(name);
Stream str = entry.Open();
MemoryStream ms = new MemoryStream(unzipped);
ms.CopyTo(str);
str.Close();
}
}
outms.Seek(0, SeekOrigin.Begin);
}
var outdata = outms.ToArray();
var result = File(outdata, "application/zip", "documents.zip");
return result;
Now it creates the file but when you try to unzip it after download.
It gives me an error in WinZip. Error: unable to seek to beginning of Central Directory.
Can someone please assist I have no idea what I'm doing wrong?
you have to dispose the Stream before add new stream to zip but the real problem is that you call Seek on stream, try the following code:
using (ZipArchive zar = new ZipArchive(outms, ZipArchiveMode.Create, false))
{
foreach (Document docu in docs)
{
if (docu != null)
{
byte[] documentdata = documentService.DownloadDocumentData(docu.DocumentID);
string name = docu.DocumentNiceName ?? docu.DocumentFileName;
byte[] unzipped = documentdata;
ZipArchiveEntry entry = zar.CreateEntry(name);
using (Stream str = entry.Open())
{
str.Write(unzipped);
}
}
}
//outms.Seek(0, SeekOrigin.Begin); //This causes "Error: unable to seek to beginning of Central Directory."
}
var outdata = outms.ToArray();
var result = File(outdata, "application/zip", "documents.zip");
return result;

Zip S3 files using C#

What I'm looking for is zip/compress S3 files without having them first downloaded to EFS or on a file system and then upload the zip file back to S3. Is there a C# way to achieve the same? I found the following post, but not sure its C# equivalent
https://www.antstack.io/blog/create-zip-using-lambda-with-files-streamed-from-s3/
I've written following code to zip files from a MemoryStream
public static void CreateZip(string zipFileName, List<FileInfo> filesToZip)
{
//zipFileName is the final zip file name
LambdaLogger.Log($"Zipping in progress for: {zipFileName}");
using (MemoryStream zipMS = new MemoryStream())
{
using (ZipArchive zipArchive = new ZipArchive(zipMS, ZipArchiveMode.Create, true))
{
//loop through files to add
foreach (var fileToZip in filesToZip)
{
//read the file bytes
byte[] fileToZipBytes = File.ReadAllBytes(fileToZip.FullName);
ZipArchiveEntry zipFileEntry = zipArchive.CreateEntry(fileToZip.Name);
//add the file contents
using (Stream zipEntryStream = zipFileEntry.Open())
using (BinaryWriter zipFileBinary = new BinaryWriter(zipEntryStream))
{
zipFileBinary.Write(fileToZipBytes);
}
}
}
using (FileStream finalZipFileStream = new FileStream(zipFileName, FileMode.Create))
{
zipMS.Seek(0, SeekOrigin.Begin);
zipMS.CopyTo(finalZipFileStream);
}
}
}
But problem is how to make it read file directly from S3 and upload the compressed file.
public static async Task CreateZipFile(List<List<KeyVersion>> keyVersions)
{
using MemoryStream zipMS = new MemoryStream();
using (ZipArchive zipArchive = new ZipArchive(zipMS, ZipArchiveMode.Create, true))
{
foreach (var key in keyVersions)
{
foreach (var fileToZip in key)
{
GetObjectRequest request = new GetObjectRequest
{
BucketName = "dev-s3-zip-bucket",
Key = fileToZip.Key
};
using GetObjectResponse response = await s3client.GetObjectAsync(request);
using Stream responseStream = response.ResponseStream;
ZipArchiveEntry zipFileEntry = zipArchive.CreateEntry(fileToZip.Key);
//add the file contents
using Stream zipEntryStream = zipFileEntry.Open();
await responseStream.CopyToAsync(zipEntryStream);
}
}
zipArchive.Dispose();
}
zipMS.Seek(0, SeekOrigin.Begin);
var fileTxfr = new TransferUtility(s3client);
await fileTxfr.UploadAsync(zipMS, "dev-s3-zip-bucket", "test.zip");
}

ZipArchive Create Entry using Zip File to memory stream

I am using Zip Archive to create a zip folder with various files and subfolders and returning it as a memory stream like so.
public MemoryStream CreateAZipFolder(){
var stMarged = new System.IO.MemoryStream();
stMarged.Position = 0;
using (MemoryStream zipStream = new MemoryStream())
{
using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
{
string[] fileEntries = Directory.GetFiles(#"C:\Applications\folder");
foreach (var fileName in fileEntries)
{
zip.CreateEntryFromFile(fileName, "Applications/folder/" + Path.GetFileName(fileName),
CompressionLevel.Optimal);
}
ZipArchiveEntry batchEntry = zip.CreateEntry("mybatchFile.bat");
using (StreamWriter writer = new StreamWriter(batchEntry.Open()))
{
writer.Write(batchFile);
}
//Add the xml file to zip folder
ZipArchiveEntry entry = zip.CreateEntry("nCounterConfig.xml");
using (StreamWriter writer = new StreamWriter(entry.Open()))
{
writer.Write(xdoc.OuterXml);
}
}
zipStream.Position = 0;
return zipStream;
I would like to add a directory with sub directories and files to this memory stream. I found that ZipFile has a method "CreateFromDirectory" which would be ideal except it requires a paramater for an output folder the method also does not have a return type. How can i zip all the files and subfolders in a directory and add them to my memory stream using ZipFile?
something like this
zip.CreateEntry(ZipFile.CreateFromDirectory(
#"C:\morefilestozip\", "",
CompressionLevel.Fastest, true));

.NET Core Created Zip Archive is corrupted [duplicate]

I'm trying to create a ZIP archive with a simple demo text file using a MemoryStream as follows:
using (var memoryStream = new MemoryStream())
using (var archive = new ZipArchive(memoryStream , ZipArchiveMode.Create))
{
var demoFile = archive.CreateEntry("foo.txt");
using (var entryStream = demoFile.Open())
using (var streamWriter = new StreamWriter(entryStream))
{
streamWriter.Write("Bar!");
}
using (var fileStream = new FileStream(#"C:\Temp\test.zip", FileMode.Create))
{
stream.CopyTo(fileStream);
}
}
If I run this code, the archive file itself is created but foo.txt isn't.
However, if I replace the MemoryStream directly with the file stream, the archive is created correctly:
using (var fileStream = new FileStream(#"C:\Temp\test.zip", FileMode.Create))
using (var archive = new ZipArchive(fileStream, FileMode.Create))
{
// ...
}
Is it possible to use a MemoryStream to create the ZIP archive without the FileStream?
Thanks to ZipArchive creates invalid ZIP file, I got:
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
var demoFile = archive.CreateEntry("foo.txt");
using (var entryStream = demoFile.Open())
using (var streamWriter = new StreamWriter(entryStream))
{
streamWriter.Write("Bar!");
}
}
using (var fileStream = new FileStream(#"C:\Temp\test.zip", FileMode.Create))
{
memoryStream.Seek(0, SeekOrigin.Begin);
memoryStream.CopyTo(fileStream);
}
}
That indicated we need to call Dispose on ZipArchive before we can use it, which as Amir suggests is likely because it writes final bytes like checksum to the archive that makes it complete. But in order not close the stream so we can re-use it after you need to pass true as the third parameter to ZipArchive.
Just another version of zipping without writing any file.
string fileName = "export_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".xlsx";
byte[] fileBytes = here is your file in bytes
byte[] compressedBytes;
string fileNameZip = "Export_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".zip";
using (var outStream = new MemoryStream())
{
using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
{
var fileInArchive = archive.CreateEntry(fileName, CompressionLevel.Optimal);
using (var entryStream = fileInArchive.Open())
using (var fileToCompressStream = new MemoryStream(fileBytes))
{
fileToCompressStream.CopyTo(entryStream);
}
}
compressedBytes = outStream.ToArray();
}
Set the position of the stream to the 0 before copying it to the zip stream.
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
var demoFile = archive.CreateEntry("foo.txt");
using (var entryStream = demoFile.Open())
using (var streamWriter = new StreamWriter(entryStream))
{
streamWriter.Write("Bar!");
}
}
using (var fileStream = new FileStream(#"C:\Temp\test.zip", FileMode.Create))
{
memoryStream.Position=0;
memoryStream.WriteTo(fileStream);
}
}
Working solution for MVC
public ActionResult Index()
{
string fileName = "test.pdf";
string fileName1 = "test.vsix";
string fileNameZip = "Export_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".zip";
byte[] fileBytes = System.IO.File.ReadAllBytes(#"C:\test\test.pdf");
byte[] fileBytes1 = System.IO.File.ReadAllBytes(#"C:\test\test.vsix");
byte[] compressedBytes;
using (var outStream = new MemoryStream())
{
using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
{
var fileInArchive = archive.CreateEntry(fileName, CompressionLevel.Optimal);
using (var entryStream = fileInArchive.Open())
using (var fileToCompressStream = new MemoryStream(fileBytes))
{
fileToCompressStream.CopyTo(entryStream);
}
var fileInArchive1 = archive.CreateEntry(fileName1, CompressionLevel.Optimal);
using (var entryStream = fileInArchive1.Open())
using (var fileToCompressStream = new MemoryStream(fileBytes1))
{
fileToCompressStream.CopyTo(entryStream);
}
}
compressedBytes = outStream.ToArray();
}
return File(compressedBytes, "application/zip", fileNameZip);
}
You need to finish writing the memory stream then read the buffer back.
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create))
{
var demoFile = archive.CreateEntry("foo.txt");
using (var entryStream = demoFile.Open())
using (var streamWriter = new StreamWriter(entryStream))
{
streamWriter.Write("Bar!");
}
}
using (var fileStream = new FileStream(#"C:\Temp\test.zip", FileMode.Create))
{
var bytes = memoryStream.GetBuffer();
fileStream.Write(bytes,0,bytes.Length );
}
}
using System;
using System.IO;
using System.IO.Compression;
namespace ConsoleApplication
{
class Program`enter code here`
{
static void Main(string[] args)
{
using (FileStream zipToOpen = new FileStream(#"c:\users\exampleuser\release.zip", FileMode.Open))
{
using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
{
ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt");
using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
{
writer.WriteLine("Information about this package.");
writer.WriteLine("========================");
}
}
}
}
}
}
Function to return stream that contain zip file
public static Stream ZipGenerator(List<string> files)
{
ZipArchiveEntry fileInArchive;
Stream entryStream;
int i = 0;
List<byte[]> byteArray = new List<byte[]>();
foreach (var file in files)
{
byteArray.Add(File.ReadAllBytes(file));
}
var outStream = new MemoryStream();
using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
{
foreach (var file in files)
{
fileInArchive=(archive.CreateEntry(Path.GetFileName(file), CompressionLevel.Optimal));
using (entryStream = fileInArchive.Open())
{
using (var fileToCompressStream = new MemoryStream(byteArray[i]))
{
fileToCompressStream.CopyTo(entryStream);
}
i++;
}
}
}
outStream.Position = 0;
return outStream;
}
If you want , write zip to file stream.
using (var fileStream = new FileStream(#"D:\Tools\DBExtractor\DBExtractor\bin\Debug\test.zip", FileMode.Create))
{
outStream.Position = 0;
outStream.WriteTo(fileStream);
}
`
I'm late to the party, but there are scenarios where you can't access the ZipArchive's constructor to set the leaveOpen parameter and where you don't want the ZIP to be written to disk. In my case, the AsiceArchive class I'm using internally creates a ZipArchive but doesn't set leaveOpen to true.
I created a subclass of Stream that delegates all calls to an inner stream (a few clicks with ReSharper). This class is not disposable, so when the ZipArchive gets disposed, nothing happens to the inner stream.
public class NondisposingStreamWrapper : Stream
{
private readonly Stream _streamImplementation;
public NondisposingStreamWrapper(Stream inner) => _streamImplementation = inner;
public override void Flush() => _streamImplementation.Flush();
public override int Read(byte[] buffer, int offset, int count) => _streamImplementation.Read(buffer, offset, count);
public override long Seek(long offset, SeekOrigin origin) => _streamImplementation.Seek(offset, origin);
public override void SetLength(long value) => _streamImplementation.SetLength(value);
public override void Write(byte[] buffer, int offset, int count) => _streamImplementation.Write(buffer, offset, count);
public override bool CanRead => _streamImplementation.CanRead;
public override bool CanSeek => _streamImplementation.CanSeek;
public override bool CanWrite => _streamImplementation.CanWrite;
public override long Length => _streamImplementation.Length;
public override long Position
{
get => _streamImplementation.Position;
set => _streamImplementation.Position = value;
}
}
Use it like this:
using var memoryStream = new MemoryStream();
var output = new NondisposingStreamWrapper(memoryStream);
using (var archive = new ZipArchive(output, ZipArchiveMode.Create))
{
// add entries to archive
}
memoryStream.Flush();
memoryStream.Position = 0;
// write to file just for testing purposes
File.WriteAllBytes("out.zip", memoryStream.ToArray());
This is the way to convert a entity to XML File and then compress it:
private void downloadFile(EntityXML xml) {
string nameDownloadXml = "File_1.xml";
string nameDownloadZip = "File_1.zip";
var serializer = new XmlSerializer(typeof(EntityXML));
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.AddHeader("content-disposition", "attachment;filename=" + nameDownloadZip);
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
var demoFile = archive.CreateEntry(nameDownloadXml);
using (var entryStream = demoFile.Open())
using (StreamWriter writer = new StreamWriter(entryStream, System.Text.Encoding.UTF8))
{
serializer.Serialize(writer, xml);
}
}
using (var fileStream = Response.OutputStream)
{
memoryStream.Seek(0, SeekOrigin.Begin);
memoryStream.CopyTo(fileStream);
}
}
Response.End();
}
Just in case, if anyone wants to save a dynamic zip file through SaveFileDialog.
var logFileName = "zip_filename.zip";
appLogSaver.FileName = logFileName;
appLogSaver.Filter = "LogFiles|*.zip";
appLogSaver.DefaultExt = "zip";
DialogResult resDialog = appLogSaver.ShowDialog();
if (resDialog.ToString() == "OK")
{
System.IO.FileStream fs = (System.IO.FileStream)appLogSaver.OpenFile();
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
var demoFile = archive.CreateEntry("foo.txt");
using (var entryStream = demoFile.Open())
{
using (var streamWriter = new StreamWriter(entryStream))
{
//read your existing file and put the content here
streamWriter.Write("Bar!");
}
}
var demoFile2 = archive.CreateEntry("foo2.txt");
using (var entryStream = demoFile2.Open())
{
using (var streamWriter = new StreamWriter(entryStream))
{
streamWriter.Write("Bar2!");
}
}
}
memoryStream.Seek(0, SeekOrigin.Begin);
memoryStream.CopyTo(fs);
}
fs.Close();
}
For me something like this was ok:
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
var file = archive.CreateEntry("file.json");
using var entryStream = file.Open();
using var streamWriter = new StreamWriter(entryStream);
streamWriter.WriteLine(someJsonLine);
}
}
private void button6_Click(object sender, EventArgs e)
{
//create With Input FileNames
AddFileToArchive_InputByte(new ZipItem[]{ new ZipItem( #"E:\b\1.jpg",#"images\1.jpg"),
new ZipItem(#"E:\b\2.txt",#"text\2.txt")}, #"C:\test.zip");
//create with input stream
AddFileToArchive_InputByte(new ZipItem[]{ new ZipItem(File.ReadAllBytes( #"E:\b\1.jpg"),#"images\1.jpg"),
new ZipItem(File.ReadAllBytes(#"E:\b\2.txt"),#"text\2.txt")}, #"C:\test.zip");
//Create Archive And Return StreamZipFile
MemoryStream GetStreamZipFile = AddFileToArchive(new ZipItem[]{ new ZipItem( #"E:\b\1.jpg",#"images\1.jpg"),
new ZipItem(#"E:\b\2.txt",#"text\2.txt")});
//Extract in memory
ZipItem[] ListitemsWithBytes = ExtractItems(#"C:\test.zip");
//Choese Files For Extract To memory
List<string> ListFileNameForExtract = new List<string>(new string[] { #"images\1.jpg", #"text\2.txt" });
ListitemsWithBytes = ExtractItems(#"C:\test.zip", ListFileNameForExtract);
// Choese Files For Extract To Directory
ExtractItems(#"C:\test.zip", ListFileNameForExtract, "c:\\extractFiles");
}
public struct ZipItem
{
string _FileNameSource;
string _PathinArchive;
byte[] _Bytes;
public ZipItem(string __FileNameSource, string __PathinArchive)
{
_Bytes=null ;
_FileNameSource = __FileNameSource;
_PathinArchive = __PathinArchive;
}
public ZipItem(byte[] __Bytes, string __PathinArchive)
{
_Bytes = __Bytes;
_FileNameSource = "";
_PathinArchive = __PathinArchive;
}
public string FileNameSource
{
set
{
FileNameSource = value;
}
get
{
return _FileNameSource;
}
}
public string PathinArchive
{
set
{
_PathinArchive = value;
}
get
{
return _PathinArchive;
}
}
public byte[] Bytes
{
set
{
_Bytes = value;
}
get
{
return _Bytes;
}
}
}
public void AddFileToArchive(ZipItem[] ZipItems, string SeveToFile)
{
MemoryStream memoryStream = new MemoryStream();
//Create Empty Archive
ZipArchive archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);
foreach (ZipItem item in ZipItems)
{
//Create Path File in Archive
ZipArchiveEntry FileInArchive = archive.CreateEntry(item.PathinArchive);
//Open File in Archive For Write
var OpenFileInArchive = FileInArchive.Open();
//Read Stream
FileStream fsReader = new FileStream(item.FileNameSource, FileMode.Open, FileAccess.Read);
byte[] ReadAllbytes = new byte[4096];//Capcity buffer
int ReadByte = 0;
while (fsReader.Position != fsReader.Length)
{
//Read Bytes
ReadByte = fsReader.Read(ReadAllbytes, 0, ReadAllbytes.Length);
//Write Bytes
OpenFileInArchive.Write(ReadAllbytes, 0, ReadByte);
}
fsReader.Dispose();
OpenFileInArchive.Close();
}
archive.Dispose();
using (var fileStream = new FileStream(SeveToFile, FileMode.Create))
{
memoryStream.Seek(0, SeekOrigin.Begin);
memoryStream.CopyTo(fileStream);
}
}
public MemoryStream AddFileToArchive(ZipItem[] ZipItems)
{
MemoryStream memoryStream = new MemoryStream();
//Create Empty Archive
ZipArchive archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);
foreach (ZipItem item in ZipItems)
{
//Create Path File in Archive
ZipArchiveEntry FileInArchive = archive.CreateEntry(item.PathinArchive);
//Open File in Archive For Write
var OpenFileInArchive = FileInArchive.Open();
//Read Stream
FileStream fsReader = new FileStream(item.FileNameSource, FileMode.Open, FileAccess.Read);
byte[] ReadAllbytes = new byte[4096];//Capcity buffer
int ReadByte = 0;
while (fsReader.Position != fsReader.Length)
{
//Read Bytes
ReadByte = fsReader.Read(ReadAllbytes, 0, ReadAllbytes.Length);
//Write Bytes
OpenFileInArchive.Write(ReadAllbytes, 0, ReadByte);
}
fsReader.Dispose();
OpenFileInArchive.Close();
}
archive.Dispose();
return memoryStream;
}
public void AddFileToArchive_InputByte(ZipItem[] ZipItems, string SeveToFile)
{
MemoryStream memoryStream = new MemoryStream();
//Create Empty Archive
ZipArchive archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);
foreach (ZipItem item in ZipItems)
{
//Create Path File in Archive
ZipArchiveEntry FileInArchive = archive.CreateEntry(item.PathinArchive);
//Open File in Archive For Write
var OpenFileInArchive = FileInArchive.Open();
//Read Stream
// FileStream fsReader = new FileStream(item.FileNameSource, FileMode.Open, FileAccess.Read);
byte[] ReadAllbytes = new byte[4096];//Capcity buffer
int ReadByte = 4096 ;int TotalWrite=0;
while (TotalWrite != item.Bytes.Length)
{
if(TotalWrite+4096>item.Bytes.Length)
ReadByte=item.Bytes.Length-TotalWrite;
Array.Copy(item.Bytes, TotalWrite, ReadAllbytes, 0, ReadByte);
//Write Bytes
OpenFileInArchive.Write(ReadAllbytes, 0, ReadByte);
TotalWrite += ReadByte;
}
OpenFileInArchive.Close();
}
archive.Dispose();
using (var fileStream = new FileStream(SeveToFile, FileMode.Create))
{
memoryStream.Seek(0, SeekOrigin.Begin);
memoryStream.CopyTo(fileStream);
}
}
public MemoryStream AddFileToArchive_InputByte(ZipItem[] ZipItems)
{
MemoryStream memoryStream = new MemoryStream();
//Create Empty Archive
ZipArchive archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);
foreach (ZipItem item in ZipItems)
{
//Create Path File in Archive
ZipArchiveEntry FileInArchive = archive.CreateEntry(item.PathinArchive);
//Open File in Archive For Write
var OpenFileInArchive = FileInArchive.Open();
//Read Stream
// FileStream fsReader = new FileStream(item.FileNameSource, FileMode.Open, FileAccess.Read);
byte[] ReadAllbytes = new byte[4096];//Capcity buffer
int ReadByte = 4096 ;int TotalWrite=0;
while (TotalWrite != item.Bytes.Length)
{
if(TotalWrite+4096>item.Bytes.Length)
ReadByte=item.Bytes.Length-TotalWrite;
Array.Copy(item.Bytes, TotalWrite, ReadAllbytes, 0, ReadByte);
//Write Bytes
OpenFileInArchive.Write(ReadAllbytes, 0, ReadByte);
TotalWrite += ReadByte;
}
OpenFileInArchive.Close();
}
archive.Dispose();
return memoryStream;
}
public void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName)
{
//Opens the zip file up to be read
using (ZipArchive archive = ZipFile.OpenRead(sourceArchiveFileName))
{
if (Directory.Exists(destinationDirectoryName)==false )
Directory.CreateDirectory(destinationDirectoryName);
//Loops through each file in the zip file
archive.ExtractToDirectory(destinationDirectoryName);
}
}
public void ExtractItems(string sourceArchiveFileName,List< string> _PathFilesinArchive, string destinationDirectoryName)
{
//Opens the zip file up to be read
using (ZipArchive archive = ZipFile.OpenRead(sourceArchiveFileName))
{
//Loops through each file in the zip file
foreach (ZipArchiveEntry file in archive.Entries)
{
int PosResult = _PathFilesinArchive.IndexOf(file.FullName);
if (PosResult != -1)
{
//Create Folder
if (Directory.Exists( destinationDirectoryName + "\\" +Path.GetDirectoryName( _PathFilesinArchive[PosResult])) == false)
Directory.CreateDirectory(destinationDirectoryName + "\\" + Path.GetDirectoryName(_PathFilesinArchive[PosResult]));
Stream OpenFileGetBytes = file.Open();
FileStream FileStreamOutput = new FileStream(destinationDirectoryName + "\\" + _PathFilesinArchive[PosResult], FileMode.Create);
byte[] ReadAllbytes = new byte[4096];//Capcity buffer
int ReadByte = 0; int TotalRead = 0;
while (TotalRead != file.Length)
{
//Read Bytes
ReadByte = OpenFileGetBytes.Read(ReadAllbytes, 0, ReadAllbytes.Length);
TotalRead += ReadByte;
//Write Bytes
FileStreamOutput.Write(ReadAllbytes, 0, ReadByte);
}
FileStreamOutput.Close();
OpenFileGetBytes.Close();
_PathFilesinArchive.RemoveAt(PosResult);
}
if (_PathFilesinArchive.Count == 0)
break;
}
}
}
public ZipItem[] ExtractItems(string sourceArchiveFileName)
{
List< ZipItem> ZipItemsReading = new List<ZipItem>();
//Opens the zip file up to be read
using (ZipArchive archive = ZipFile.OpenRead(sourceArchiveFileName))
{
//Loops through each file in the zip file
foreach (ZipArchiveEntry file in archive.Entries)
{
Stream OpenFileGetBytes = file.Open();
MemoryStream memstreams = new MemoryStream();
byte[] ReadAllbytes = new byte[4096];//Capcity buffer
int ReadByte = 0; int TotalRead = 0;
while (TotalRead != file.Length)
{
//Read Bytes
ReadByte = OpenFileGetBytes.Read(ReadAllbytes, 0, ReadAllbytes.Length);
TotalRead += ReadByte;
//Write Bytes
memstreams.Write(ReadAllbytes, 0, ReadByte);
}
memstreams.Position = 0;
OpenFileGetBytes.Close();
memstreams.Dispose();
ZipItemsReading.Add(new ZipItem(memstreams.ToArray(),file.FullName));
}
}
return ZipItemsReading.ToArray();
}
public ZipItem[] ExtractItems(string sourceArchiveFileName,List< string> _PathFilesinArchive)
{
List< ZipItem> ZipItemsReading = new List<ZipItem>();
//Opens the zip file up to be read
using (ZipArchive archive = ZipFile.OpenRead(sourceArchiveFileName))
{
//Loops through each file in the zip file
foreach (ZipArchiveEntry file in archive.Entries)
{
int PosResult = _PathFilesinArchive.IndexOf(file.FullName);
if (PosResult!= -1)
{
Stream OpenFileGetBytes = file.Open();
MemoryStream memstreams = new MemoryStream();
byte[] ReadAllbytes = new byte[4096];//Capcity buffer
int ReadByte = 0; int TotalRead = 0;
while (TotalRead != file.Length)
{
//Read Bytes
ReadByte = OpenFileGetBytes.Read(ReadAllbytes, 0, ReadAllbytes.Length);
TotalRead += ReadByte;
//Write Bytes
memstreams.Write(ReadAllbytes, 0, ReadByte);
}
//Create item
ZipItemsReading.Add(new ZipItem(memstreams.ToArray(),file.FullName));
OpenFileGetBytes.Close();
memstreams.Dispose();
_PathFilesinArchive.RemoveAt(PosResult);
}
if (_PathFilesinArchive.Count == 0)
break;
}
}
return ZipItemsReading.ToArray();
}

ZipArchive returning Empty Folder C#

I am using ZipArchive to create a zipped folder for a list of documents.
I cant figure out why, when I return my archived folder it is empty.
Does anyone see what I am doing wrong here?
My code is as follows:
if (files.Count > 1)
{
var ms = new MemoryStream();
var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, false);
foreach (var file in files)
{
var entry = zipArchive.CreateEntry(file.UploadFileName, CompressionLevel.Fastest);
using (var streamWriter = new StreamWriter(entry.Open()))
{
Stream strFile = new MemoryStream(file.UploadFileBytesStream);
streamWriter.Write(strFile);
strFile.CopyTo(ms);
}
}
return File(ms, System.Net.Mime.MediaTypeNames.Application.Zip, "FinancialActivityReports.zip");
}
Assuming the following model for file
public class FileModel {
public string UploadFileName { get; set; }
public byte[] UploadFileBytesStream { get; set; }
}
The following helper was written to create the stream of the compressed files
public static class FileModelCompression {
public static Stream Compress(this IEnumerable<FileModel> files) {
if (files.Any()) {
var ms = new MemoryStream();
var archive = new ZipArchive(ms, ZipArchiveMode.Create, false);
foreach (var file in files) {
var entry = archive.add(file);
}
ms.Position = 0;
return ms;
}
return null;
}
private static ZipArchiveEntry add(this ZipArchive archive, FileModel file) {
var entry = archive.CreateEntry(file.UploadFileName, CompressionLevel.Fastest);
using (var stream = entry.Open()) {
stream.Write(file.UploadFileBytesStream, 0, file.UploadFileBytesStream.Length);
stream.Position = 0;
stream.Close();
}
return entry;
}
}
You code, assuming files is derived from IEnumerable<FileModel> will then change to this...
if (files.Count > 1)
{
var stream = files.Compress();
return File(stream, System.Net.Mime.MediaTypeNames.Application.Zip, "FinancialActivityReports.zip");
}

Categories

Resources