首页 > 解决方案 > Azure 功能:解压缩文件在调试中有效,但在生产中无效

问题描述

这是我的第一个 Azure 函数。在将文件上传到 Azure 存储 Blob 后,我需要解压缩文件。
我发现了这个视频https://www.youtube.com/watch?v=GRztpy337kU和这篇文章:https://msdevzone.wordpress.com/2017/07/07/extract-a-zip-file-stored-in -天蓝色斑点
使用带有 C# 的 Visual Studio 2017,当我在 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

一切似乎都很好,但在函数结束时容器输出文件是空的!

我究竟做错了什么?

标签: c#azureazure-functions

解决方案


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

blockBlob.UploadFromStreamAsync(fileStream);

它需要改为:

await blockBlob.UploadFromStreamAsync(fileStream);

和你的功能本身:

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

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

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");
            }
        }
    }
}

推荐阅读