Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在Azure文件存储中解压缩一个大的zip文件w/o“;“内存不足”;例外情况;_C#_.net_Azure_Zip - Fatal编程技术网

C# 在Azure文件存储中解压缩一个大的zip文件w/o“;“内存不足”;例外情况;

C# 在Azure文件存储中解压缩一个大的zip文件w/o“;“内存不足”;例外情况;,c#,.net,azure,zip,C#,.net,Azure,Zip,这就是我要处理的 某些进程(我们无法控制)偶尔会将zip文件放入Azure文件存储的目录中。该目录名为入站。假设一个名为bigbook.zip的文件被放入InBound文件夹 我需要创建一个Azure Function应用程序,它每5分钟运行一次,并在入站目录中查找zip文件。如果存在任何目录,则逐个创建一个与另一个目录中的zip文件同名的新目录(称为InProcess)。因此,在我们的示例中,我将创建InProcess/bigbook 现在在InProcess/bigbook中,我需要解压缩b

这就是我要处理的

某些进程(我们无法控制)偶尔会将zip文件放入Azure文件存储的目录中。该目录名为
入站
。假设一个名为
bigbook.zip
的文件被放入
InBound
文件夹

我需要创建一个Azure Function应用程序,它每5分钟运行一次,并在
入站
目录中查找zip文件。如果存在任何目录,则逐个创建一个与另一个目录中的zip文件同名的新目录(称为
InProcess
)。因此,在我们的示例中,我将创建
InProcess/bigbook

现在在
InProcess/bigbook
中,我需要解压缩
bigbook.zip
。因此,当进程完成时,运行
InProcess/bigbook
将包含
bigbook.zip
的所有内容

请注意:我正在创建的这个函数是一个控制台应用程序,将作为Azure函数应用程序运行。因此,将没有文件系统访问权限(至少,据我所知,无论如何)。没有下载zip文件、解压缩然后移动内容的选项

我花了很长时间才弄明白如何在记忆中做到这一点。无论我尝试什么,我总是遇到内存不足的异常。目前,我只是在Visual Studio 2017、.NET 4.7中运行调试的本地主机上执行此操作。在该设置中,我无法转换测试zip文件,该文件为515069KB

这是我第一次尝试:

    private async Task<MemoryStream> GetMemoryStreamAsync(CloudFile inBoundfile)
    {
        MemoryStream memstream = new MemoryStream();
        await inBoundfile.DownloadToStreamAsync(memstream).ConfigureAwait(false);
        return memstream;
    }
但不管怎样,我都遇到了内存问题。我想这是因为我试图创建的内存流太大了吧

我还能怎么解决这个问题?同样,下载zip文件不是一个选项,因为该应用程序最终将是一个Azure功能应用程序。我还非常确定使用文件流也不是一个选项,因为它需要本地文件路径,而我没有。(我只有一个远程Azure URL)

我是否可以在zip文件所在的同一Azure存储帐户中创建一个临时文件,并将zip文件流式传输到该临时文件而不是内存流?(大声思考。)

目标是使用以下方法将流放入
ZipArchive

ZipArchive archive = new ZipArchive(stream)
从那里我可以提取所有的内容。但要做到这一点,没有内存错误是一个真正的问题


有什么想法吗?

我建议您使用内存快照来了解Visual Studio内存不足的原因。您可以使用中的教程查找罪犯。如果您的计算机内存不足,使用较小的文件进行本地开发可以帮助您继续工作

在Azure中执行此操作时,消费计划中的一个节点是。如果你希望收到比这更大的文件,那么你应该看看其他的应用程序服务计划,它会给你更多的内存


可以在中存储文件,因此这是一个选项。您无法保证在执行之间使用相同的本地目录,但只要您在同一执行中使用下载的文件,这应该可以正常工作。

使用Azure存储文件共享这是唯一一种在不将整个ZIP加载到内存的情况下对我有效的方法。我使用3GB的ZIP文件(包含数千个文件或一个大文件)进行测试,内存/CPU低且稳定。我希望有帮助

var zipFiles = _directory.ListFilesAndDirectories()
    .OfType<CloudFile>()
    .Where(x => x.Name.ToLower().Contains(".zip"))
    .ToList();

foreach (var zipFile in zipFiles)
{
    using (var zipArchive = new ZipArchive(zipFile.OpenRead()))
    {
        foreach (var entry in zipArchive.Entries)
        {
            if (entry.Length > 0)
            {
                CloudFile extractedFile = _directory.GetFileReference(entry.Name);

                using (var entryStream = entry.Open())
                {
                    byte[] buffer = new byte[16 * 1024];
                    using (var ms = extractedFile.OpenWrite(entry.Length))
                    {
                        int read;
                        while ((read = entryStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            ms.Write(buffer, 0, read);
                        }
                    }
                }
            }
        }
    }               
}
var zipFiles=\u directory.ListFilesAndDirectories()
第()类
.Where(x=>x.Name.ToLower().Contains(“.zip”))
.ToList();
foreach(zipFiles中的变量zipFile)
{
使用(var zipArchive=new zipArchive(zipFile.OpenRead())
{
foreach(zipArchive.Entries中的var条目)
{
如果(entry.Length>0)
{
CloudFile extractedFile=\u directory.GetFileReference(entry.Name);
使用(var entryStream=entry.Open())
{
字节[]缓冲区=新字节[16*1024];
使用(var ms=extractedFile.OpenWrite(entry.Length))
{
int-read;
而((read=entryStream.read(buffer,0,buffer.Length))>0)
{
ms.Write(缓冲区,0,读取);
}
}
}
}
}
}               
}

您是否尝试过使用CloudFile?CloudFile具有创建、复制和删除的方法。可能会帮你的忙。@Sean,谢谢你,但我不确定你说的我使用的是CloudFile是什么意思。我在OP中输入的两个方法都采用一个参数
(CloudFile inBoundfile)
。我需要做的是将该CloudFile转换为流,以便在“ZipArchive(stream)”中使用它。这就是我面临的全部问题。我指的是云文件类。您提到您只有Azure URL。CloudFile有一个接受URI的构造函数。你可以从你的url创建一个新的Cloudfile对象,然后打开云文件流。我仍然不知道这如何帮助我更接近我的最终目标。也许我不明白?我有一个CloudFile,您的意思是我应该使用该CloudFile的URL来创建另一个CloudFile?我需要做的是获取一个现有的CloudFile并将其转换为内存流。@CaseyCrokston,它在我的本地计算机上使用DownloadToStream(内存流)运行良好,.zip文件大约为600M。在下载过程中,我的本地计算机将占用大约6亿内存。你能把你的代码推到azure上,看看它是否工作吗?
var zipFiles = _directory.ListFilesAndDirectories()
    .OfType<CloudFile>()
    .Where(x => x.Name.ToLower().Contains(".zip"))
    .ToList();

foreach (var zipFile in zipFiles)
{
    using (var zipArchive = new ZipArchive(zipFile.OpenRead()))
    {
        foreach (var entry in zipArchive.Entries)
        {
            if (entry.Length > 0)
            {
                CloudFile extractedFile = _directory.GetFileReference(entry.Name);

                using (var entryStream = entry.Open())
                {
                    byte[] buffer = new byte[16 * 1024];
                    using (var ms = extractedFile.OpenWrite(entry.Length))
                    {
                        int read;
                        while ((read = entryStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            ms.Write(buffer, 0, read);
                        }
                    }
                }
            }
        }
    }               
}