微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

点网内存流-如何在不消耗所有内存的情况下等待一个

如何解决点网内存流-如何在不消耗所有内存的情况下等待一个

在开始我的问题时,我会说我认为我对如何解决该问题有根本的误解,并在这里寻求一些指导以潜在地了解我不知道的哈哈。

在没有深入研究具体细节的情况下,我遇到的问题是我正在基于流式传输来自S3的文件列表以编程方式编写Zip文件。当执行此操作作为对浏览器的响应时,它几乎不使用任何内存。但是,当我尝试将所有内容都写到一个内存流中并将Zip上传到S3时,它会占用大量内存,并且可以非常快地推翻Pod(服务在k8s中运行)。

在编写浏览器时,最终将返回它:

return new StreamingFileResult
(
    contentType: download.GetContentType(),attachmentFileName: Path.GetFileName(download.Path),statusCode: HttpStatusCode.OK,writeResponseBody: async (s) => await download.WritetoStream(s,_downloadBufferSize,cancellationToken)
);

这是WritetoStream()类中的ZipDownload的样子:

public override async Task WritetoStream(Stream outputStream,int bufferSize,CancellationToken cancellationToken)
{
    using (var zipArchive = new ZipArchive(outputStream,ZipArchiveMode.Create))
    {
        foreach (IDownload download in _downloads)
        {
            var zipEntry = zipArchive.CreateEntry(download.OutFilename);

            using (var zipStream = zipEntry.open())
            {
                await download.WritetoStream(zipStream,bufferSize,cancellationToken);
                // NOTE FOR STACK: This is from a separate method,specifically from an S3Download class
            }
        }
    }
}

这部分不占用太多内存,这对我来说很有意义。通过将Task写入lambda,它正在等待操作结束,并将所有内容都写回到outputStream,该变量由所述lambda初始化。一切都很好。

现在对我来说最困难的部分是当我们将文件上传到S3而不是浏览器时。

它看起来像这样:

 await upload.S3Upload(download,zipInfo.BucketName,zipInfo.FileName,cancellationToken);

// then in our uploader file
try
{
    using(var fileTransferUtility = new TransferUtility(s3Client))
    {
        Logger.LogInfo("Starting Upload for {0}",keyName);
         fileTransferUtility.Upload(await download.WritetoStream(_downloadBufferSize,cancellationToken),bucketName,keyName);
        Logger.LogInfo("Finished Upload!");
        return;
    }
}

它使用的是WritetoStreamZipDownload的重载版本,它返回一个Task<Stream>

public override async Task<Stream> WritetoStream(int bufferSize,CancellationToken cancellationToken)
{
    Stream outputStream = new MemoryStream();
    using (var zipArchive = new ZipArchive(outputStream,ZipArchiveMode.Create,true))
    {
        foreach (IDownload download in _downloads)
        {
            var zipEntry = zipArchive.CreateEntry(download.OutFilename);

            using (var zipStream = zipEntry.open())
            {
                await download.WritetoStream(zipStream,cancellationToken);
            }
        }
    }
    return outputStream;
}

其背后的逻辑是因为TransferUtility需要一个Stream,而且我无法运行Lambda /委托,所以选择直接从Task返回Stream。

现在,我相信内存会变得疯狂的原因尤其是由于上传文件中的fileTransferUtility.Upload(await download.WritetoStream(_downloadBufferSize,keyName);以及我们如何拥有await download.WritetoStream()。我认为它正在等待整个过程完成,然后再将结果泵入TransferUtility,这与浏览器的实现有很大不同。我觉得我们不希望这不是积累而是 迭代 ,但是我不确定如何实现。

关于帮助我如何实现此目标的任何提示?也许有明显的我想念的地方=]

谢谢!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?