Azure功能:解压缩文件可在调试中使用,但不能在生产中使用

时间:2019-10-09 14:24:03

标签: c# azure azure-functions

这是我的第一个Azure函数。将文件上传到Azure存储Blob之后,我需要解压缩文件。
我找到了这段视频https://www.youtube.com/watch?v=GRztpy337kU和这篇帖子:https://msdevzone.wordpress.com/2017/07/07/extract-a-zip-file-stored-in-azure-blob
将Visual Studio 2017与C#结合使用时,当我在Visual Studio中运行该功能时一切正常,但是当我将其部署到Azure时,不会提取任何内容。如果我看日志,一切正常。
这是我的代码:

using System;
using System.IO;
using System.IO.Compression;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.WindowsAzure.Storage;

namespace ExtractZipFunction
{
    public static class ScompattaZip
    {
        [FunctionName("ScompattaZip")]
        public static void Run([BlobTrigger("input-files/{name}", Connection = "connectionStorage")]
                                Stream myBlob, string name, TraceWriter log)

        {
            log.Info($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
            try
            {
                string destinationStorage = Environment.GetEnvironmentVariable("destinationStorage");
                string destinationContainer = Environment.GetEnvironmentVariable("destinationContainer");
                log.Info($"destinationStorage: {destinationStorage}");
                log.Info($"destinationContainer: {destinationContainer}");

                if (System.IO.Path.GetExtension(name).ToLower() == ".zip")
                {
                    log.Info("It's a zip");
                    var archive = new ZipArchive(myBlob);
                    var storageAccount = CloudStorageAccount.Parse(destinationStorage);
                    var blobClient = storageAccount.CreateCloudBlobClient();
                    var container = blobClient.GetContainerReference(destinationContainer);

                    foreach (var entry in archive.Entries)
                    {
                        var blockBlob = container.GetBlockBlobReference(entry.FullName);
                        using (var fileStream = entry.Open())
                        {
                            if (entry.Length > 0)
                            {
                                log.Info($"Estrazione 1 - {entry.FullName}");
                                blockBlob.UploadFromStreamAsync(fileStream);
                                log.Info($"Estrazione 2 - {entry.FullName}");
                            }
                        }
                    }
                }
                else
                    log.Info("Not a zip");
            }
            catch (Exception ex)
            {
                log.Info($"Errore: {ex.Message}");
            }
        }
    }
}

这是Azure中的日志:

C# Blob trigger function Processed blob
 Name:EmptyJSONFile_1033.zip 
 Size: 24294 Bytes
destinationStorage: DefaultEndpointsProtocol=https;AccountName=[...]
destinationContainer: outputfiles
E' uno zip
Estrazione EmptyJSONFile_1033.ico
Estrazione 1 - EmptyJSONFile_1033.ico
Estrazione 2 - EmptyJSONFile_1033.ico
Estrazione EmptyJSONFile_1033.vstemplate
Estrazione 1 - EmptyJSONFile_1033.vstemplate
Estrazione 2 - EmptyJSONFile_1033.vstemplate
Estrazione json.json
Estrazione 1 - json.json
Estrazione 2 - json.json

一切似乎都不错,但是在函数结尾处,容器的输出文件为空!

我在做什么错了?

1 个答案:

答案 0 :(得分:2)

除了我上面的评论(无论如何请这样做!),您的问题在这里:

blockBlob.UploadFromStreamAsync(fileStream);

它必须是:

await blockBlob.UploadFromStreamAsync(fileStream);

和您的函数本身:

public static async Task Run([BlobTrigger("input-files/{name}", Connection = "connectionStorage")] Stream myBlob, string name, TraceWriter log)

// Edit:所以这是使用输出绑定的完整示例。请注意,如果愿意,您当然也可以使用两个不同的连接字符串(两个不同的存储帐户)进行触发和输出绑定。

using System;
using System.IO;
using System.IO.Compression;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage.Blob;

namespace SampleFunctions
{
    public static class UnzipBlob
    {
        /// <summary>
        /// This function is triggered by new blobs (should be a ZIP file) 
        /// and extracts the contents of the zip as new, individual blobs to a storage account
        /// </summary>
        /// <param name="inputBlob"></param>
        /// <param name="inputBlobName"></param>
        /// <param name="outputContainer"></param>
        /// <param name="log"></param>
        /// <returns></returns>
        [FunctionName("UnzipBlob")]
        public static async Task Run([BlobTrigger("input-zips/{inputBlobName}", Connection = "AzureWebJobsStorage")] Stream inputBlob, string inputBlobName,
            Binder binder,
            ILogger log)
        {
            log.LogInformation($"Blob trigger function received blob\n Name:{inputBlobName} \n Size: {inputBlob.Length} Bytes");

            if (Path.GetExtension(inputBlobName)?.ToLower() == ".zip")
            {
                // We use the first char of the input file name as a dynamic part in the container. (Note: You should check if this is a valid char for the container name)
                var container = $"my-dynamic-container-{inputBlobName.Substring(0,1).ToLower()}";
                var attributes = new Attribute[]
                {
                        new BlobAttribute($"{container}", FileAccess.ReadWrite),
                        new StorageAccountAttribute("AzureWebJobsStorage")
                };
                var outputContainer = await binder.BindAsync<CloudBlobContainer>(attributes);
                await outputContainer.CreateIfNotExistsAsync();

                var archive = new ZipArchive(inputBlob);
                foreach (var entry in archive.Entries)
                {
                    // we write the output files to a directory with the same name as the input blob. Change as required
                    var blockBlob = outputContainer.GetBlockBlobReference($"{inputBlobName}/{entry.FullName}");
                    using (var fileStream = entry.Open())
                    {
                        if (entry.Length > 0)
                        {
                            log.LogInformation($"Extracting - {entry.FullName} to - {blockBlob.Name}");
                            await blockBlob.UploadFromStreamAsync(fileStream);
                        }
                    }
                }
            }
            else
            {
                log.LogInformation("Not a zip file. Ignoring");
            }
        }
    }
}