如何在内存中创建zip文件?

时间:2019-12-30 08:35:19

标签: c# asp.net-core

我必须从一组URL中创建一个zip文件。并且应该具有适当的文件夹结构。 所以我尝试了

   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;
        }
    }

目前我正在将所有文件写入我的基本目录(可能不是一个好主意)。目前,我必须手动删除所有文件夹和文件,以避免出现异常/不需要的文件。一切都可以写在内存中吗?

将所有文件和文件夹结构写入内存需要进行哪些更改?

2 个答案:

答案 0 :(得分:1)

不,你不能。不能通过内置的Dotnet来实现。

enter image description here

根据我的评论,我建议将文件存储在基于Guid或类似文件的自定义位置。例如:

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

这将确保您可以处理具有相同文件或相似文件/文件夹名称的多个请求。

然后,您只需要清理并随后再次删除该文件夹,这样就不会用完空间。

答案 1 :(得分:0)

希望下面的代码可以完成工作。

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;
            }
        }