如何使用 Azure Function 在 Azure 文件共享中解压缩文件?

Posted

技术标签:

【中文标题】如何使用 Azure Function 在 Azure 文件共享中解压缩文件?【英文标题】:How to unzip file in Azure File Share using Azure Function? 【发布时间】:2021-02-07 03:51:10 【问题描述】:

我有一个带有 Azure 文件共享的 Azure 存储帐户。我想使用 Azure 函数将 zip 存档文件提取到文件共享中的另一个目录。我用 C# 编写了这段代码:

    CloudFileDirectory rootDirectory = cloudFileShare.GetRootDirectoryReference();
    CloudFileDirectory output = rootDirectory.GetDirectoryReference("output");
    CloudFile cloudFile = input.GetFileReference("archive1.zip");
    
    using (var stream = await cloudFile.OpenReadAsync())
    

       var file1 = new ZipArchive(stream);

       foreach (var zipEntry in file1.Entries)
       

          var file2 = output.GetFileReference(zipEntry.Name);

          var fileStream = zipEntry.Open();

          await file2.UploadFromStreamAsync(fileStream); //error is in this line

        

   

但我得到了错误:

System.Private.CoreLib: Exception while executing function: HttpTriggerExtract. Microsoft.WindowsAzure.Storage: 
Operation is not valid due to the current state of the object.

如何解决这个问题?

编辑:此外,我使用 MemoryStream 修复了错误,此代码有效:

        foreach (var zipEntry in file1.Entries) 

            var fsz = output.GetFileReference(zipEntry.Name);

            using (var ms = new MemoryStream())
            

                using (var fileStream = zipEntry.Open())
                
                    await fileStream.CopyToAsync(ms);

                    ms.Seek(0, SeekOrigin.Begin);
                    await fsz.UploadFromStreamAsync(ms);

                

            

【问题讨论】:

您还有其他顾虑吗?如果您没有其他顾虑,可以请accept it as an answer吗?它可能会帮助更多有类似问题的人。 问题在于从 fileStream 对象获取流。我不得不使用额外的内存流,现在一切正常。 感谢您的分享。你能发表你的答案吗? 是的,我已经编辑了我的问题并添加了工作代码。请投票。 【参考方案1】:

关于问题,请参考以下代码(我使用包WindowsAzure.Storage 9.3.1来做到这一点)

            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
            CloudFileClient cloudFileClient = storageAccount.CreateCloudFileClient();
            CloudFileShare cloudFileShare = cloudFileClient.GetShareReference("share2");
            CloudFileDirectory rootDirectory = cloudFileShare.GetRootDirectoryReference();
            CloudFileDirectory input = rootDirectory.GetDirectoryReference("input");
            CloudFileDirectory output = rootDirectory.GetDirectoryReference("output");
            CloudFile cloudFile = input.GetFileReference("sample.zip");
            using (var stream = await cloudFile.OpenReadAsync())
            using (var zipArchive = new ZipArchive(stream)) 
                foreach (var entry in zipArchive.Entries)
                
                    if (entry.Length > 0) 
                        CloudFile extractedFile = output.GetFileReference(entry.Name);

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

            

【讨论】:

【参考方案2】:

以上答案帮助我解决了我的问题。 使用新的 Azure 库 (12.7.0),您必须这样编写代码:

        string srcDir = @"sourcePath";
        string destDir = @"sourcePath\testStorageUnzip";
        string srcFileName = "AzureStorageZip.zip";

        string azureConnectionString = ConfigurationManager.AppSettings["beecloudfileshare_AzureStorageConnectionString"];

        StorageSharedKeyCredential credential = BeeFileManager.GetAzureStorageKeyCredential(azureConnectionString);
        Uri srcUri = new Uri("https:" + Path.Combine(srcDir, srcFileName).Replace("\\", "/"), UriKind.Absolute);
        Uri destDirUri = new Uri("https:" + Path.Combine(destDir).Replace("\\", "/"), UriKind.Absolute);
        // Get a reference to the file we created previously
        ShareFileClient sourceFile = new ShareFileClient(srcUri, credential);

        ShareDirectoryClient shareDirectoryClient = new ShareDirectoryClient(destDirUri,credential);
        shareDirectoryClient.CreateIfNotExistsAsync().GetAwaiter().GetResult();

        using (var stream = sourceFile.OpenRead())
        using (var zipArchive = new ZipArchive(stream))
        
            foreach (var entry in zipArchive.Entries)
            
                if (entry.Length > 0)
                
                    //CloudFile extractedFile = output.GetFileReference(entry.Name);
                    Uri destUri = new Uri("https:" + Path.Combine(destDir, entry.Name).Replace("\\", "/"), UriKind.Absolute);
                    ShareFileClient extractedFile = new ShareFileClient(destUri, credential);

                    
                    using (var entryStream = entry.Open())
                    
                        using (MemoryStream ms = new MemoryStream())
                        
                            entryStream.CopyTo(ms);
                            //
                            //Sorry I have this part in another method
                            //
                            Uri fileUri = new Uri("https:" + Path.GetDirectoryName(filePath).Replace("\\", "/"), UriKind.Absolute);
                            // Get a reference to the file we created previously
                            ShareDirectoryClient directory = new ShareDirectoryClient(fileUri, credential);
                            ShareFileClient file = directory.GetFileClient(Path.GetFileName(filePath));
                            ms.Seek(0, SeekOrigin.Begin);
                            file.Create(ms.Length);
                            file.Upload(ms);
                            //
                            //
                            //
                        
                    
                

            

        
    

【讨论】:

以上是关于如何使用 Azure Function 在 Azure 文件共享中解压缩文件?的主要内容,如果未能解决你的问题,请参考以下文章

.NET Azure Function App 使用 UpsertItemAsync 上传到 CosmosDB 速度非常慢,尤其是与 Python 的 CosmosClient 相比

如何在 Azure 数据砖中使用 ucanaccess(ms 访问 jdbc 驱动程序)?

我们可以使用 Azure 存储队列作为事件源吗?

如何保持azure事件集线器连接活动以使用amqp接收批量诊断

在 Azure Blob 存储中覆盖后如何命名 csv 文件

如何捕获来自事件中心的错误 json 记录到 azure 流分析