hilda_sonica_vish
hilda_sonica_vish

Reputation: 757

How to create zip file in memory?

I have to create a zip file from set of urls. and it should have a proper folder structure. So i tried like

   public async Task<byte[]> CreateZip(Guid ownerId)
    {
        try
        {
            string startPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "zipFolder");//base folder
            if (Directory.Exists(startPath))
            {
                DeleteAllFiles(startPath);
                Directory.Delete(startPath);
            }
            Directory.CreateDirectory(startPath);

            string zipPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{ownerId.ToString()}"); //folder based on ownerid
            if (Directory.Exists(zipPath))
            {
                DeleteAllFiles(zipPath);
                Directory.Delete(zipPath);
            }

            Directory.CreateDirectory(zipPath);
            var attachemnts = await ReadByOwnerId(ownerId);

            attachemnts.Data.ForEach(i =>
            {
                var fileLocalPath = $"{startPath}\\{i.Category}";
                if (!Directory.Exists(fileLocalPath))
                {
                    Directory.CreateDirectory(fileLocalPath);
                }
                using (var client = new WebClient())
                {
                    client.DownloadFile(i.Url, $"{fileLocalPath}//{i.Flags ?? ""}_{i.FileName}");
                }
            });
            var zipFilename = $"{zipPath}//result.zip";

            if (File.Exists(zipFilename))
            {
                File.Delete(zipFilename);
            }

            ZipFile.CreateFromDirectory(startPath, zipFilename, CompressionLevel.Fastest, true);


            var result = System.IO.File.ReadAllBytes(zipFilename);
            return result;
        }
        catch (Exception ex)
        {
            var a = ex;
            return null;
        }
    }

currently im writing all files in my base directory(may be not a good idea).corrently i have to manually delete all folders and files to avoid exception/unwanted files. Can everything be written in memory?

What changes required to write all files and folder structure in memory?

Upvotes: 3

Views: 619

Answers (2)

hilda_sonica_vish
hilda_sonica_vish

Reputation: 757

Hope the below code does the job.

public async Task<byte[]> CreateZip(Guid ownerId)
        {
            try
            {
                string startPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}_zipFolder");//folder to add

                Directory.CreateDirectory(startPath);

                var attachemnts = await ReadByOwnerId(ownerId);
                attachemnts.Data = filterDuplicateAttachments(attachemnts.Data);
                //filtering youtube urls
                attachemnts.Data = attachemnts.Data.Where(i => !i.Flags.Equals("YoutubeUrl", StringComparison.OrdinalIgnoreCase)).ToList();

                attachemnts.Data.ForEach(i =>
                {
                    var fileLocalPath = $"{startPath}\\{i.Category}";
                    if (!Directory.Exists(fileLocalPath))
                    {
                        Directory.CreateDirectory(fileLocalPath);
                    }
                    using (var client = new WebClient())
                    {
                        client.DownloadFile(i.Url, $"{fileLocalPath}//{i.Flags ?? ""}_{i.FileName}");
                    }
                });

                using (var ms = new MemoryStream())
                {
                    using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, true))
                    {
                        System.IO.DirectoryInfo di = new DirectoryInfo(startPath);
                        var allFiles = di.GetFiles("",SearchOption.AllDirectories);
                        foreach (var attachment in allFiles)
                        {
                            var file = File.OpenRead(attachment.FullName);

                            var type = attachemnts.Data.Where(i => $"{ i.Flags ?? ""}_{ i.FileName}".Equals(attachment.Name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                            var entry = zipArchive.CreateEntry($"{type.Category}/{attachment.Name}", CompressionLevel.Fastest);
                            using (var entryStream = entry.Open())
                            {
                                file.CopyTo(entryStream);
                            }
                        }
                    }
                    var result = ms.ToArray();
                    return result;
                }
            }
            catch (Exception ex)
            {
                var a = ex;
                return null;
            }
        }

Upvotes: 0

Kiksen
Kiksen

Reputation: 1767

No you can't. Not with the built in Dotnet any way.

enter image description here

As per my comment I would recommend storing the files in a custom location based on a Guid or similar. Eg:

"/xxxx-xxxx-xxxx-xxxx/Folder-To-Zip/....".

This would ensure you could handle multiple requests with the same files or similar file / folder names.

Then you just have to cleanup and delete the folder again afterwards so you don't run out of space.

Upvotes: 1

Related Questions