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

问题描述

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

在没有深入研究具体细节的情况下,我遇到的问题是我正在基于流式传输来自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.JdbcOdbc...