Azure Function: Unzip file works in debug but not in production

拈花ヽ惹草 提交于 2021-01-29 08:44:09

问题


This is my very first Azure function. I need to unzip a file after it is uploaded on an Azure Storage Blob.
I found this video https://www.youtube.com/watch?v=GRztpy337kU and this post: https://msdevzone.wordpress.com/2017/07/07/extract-a-zip-file-stored-in-azure-blob.
Using Visual Studio 2017 with C#, all works fine when i run the function in Visual Studio but when i deploy it to Azure, nothing is extracted. If i watch the log all seems ok.
Here is my code:

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

And this is the log in 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

All seems OK but at the end of the function the container outputfiles is empty!

What am I doing wrong?


回答1:


Except for my comment above (please do this anyway!), you issue is here:

blockBlob.UploadFromStreamAsync(fileStream);

it needs to be instead:

await blockBlob.UploadFromStreamAsync(fileStream);

and your function itself:

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

//Edit: So here is a full example using output bindings. Note that you can of course also use two different connection strings (two different storage accounts) for trigger and output binding if you like to.

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


来源:https://stackoverflow.com/questions/58306382/azure-function-unzip-file-works-in-debug-but-not-in-production

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!