【问题标题】:How to create zip file in memory?如何在内存中创建 zip 文件?
【发布时间】:2019-12-30 08:35:19
【问题描述】:

我必须从一组 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;
        }
    }

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

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

【问题讨论】:

  • 你想要在内存中的是源文件还是最终的 ZIP 文件?要创建 ZIP 文件,您可以使用 MemoryStream;参考here
  • 我想从 urls 创建一个源文件/文件夹结构,我也想在内存中。你可以看到我的 foreach 创建文件夹。
  • 我不知道如何在内存中创建文件夹结构。根据您的部署环境,您可以在服务器上创建一个不在应用程序文件夹中的临时工作文件夹。我们经常使用这样的东西。
  • 正如@PeterSmith 所说,我将创建一个临时工作文件夹。例如一个新的 Guid,比如:“/xxxx-xxxx-xxxx-xxxx/Folder-To-Zip/....”
  • 你可以使用this question的答案。但是您必须在文件名前使用目录名称调用zipArchive.CreateEntry,例如zipArchive.CreateEntry($"{startPath}\\{attachment.FileName}"

标签: c# asp.net-core


【解决方案1】:

不,你不能。无论如何都不能使用内置的 Dotnet。

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

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

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

然后您只需要在之后再次清理并删除该文件夹,以免空间不足。

【讨论】:

    【解决方案2】:

    希望下面的代码能完成这项工作。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-23
      • 2014-06-30
      • 1970-01-01
      • 1970-01-01
      • 2014-11-16
      • 2019-05-20
      • 2012-04-18
      相关资源
      最近更新 更多