Azure C# WebJob using ImageResizer not Properly Setting Content-Type

前端 未结 1 1705
耶瑟儿~
耶瑟儿~ 2020-12-17 06:20

I\'m working on an Azure WebJob to to resize newly uploaded images. The resizing works, but the newly created images do not have their content type properly set in Blob Sto

相关标签:
1条回答
  • 2020-12-17 06:42

    You can't set the content type from your implementation:

    You need to access the CloudBlockBlob.Properties.ContentType property:

    CloudBlockBlob blob = new CloudBlockBlob(...);
    blob.Properties.ContentType = "image/...";
    blob.SetProperties();
    

    Azure Webjob SDK support Blob Binding so that you can bind directly to a blob.

    In your context, you want to bind to an input blob and create multiple output blobs.

    • Use the BlobTriggerAttribute for the input.
    • Use the BlobTriggerAttribute to bind to your output blobs. Because you want to create multiple outputs blobs, you can bind directly to the output container.

    The code of your triggered function can look like that:

    using System.IO;
    using System.Web;
    using ImageResizer;
    using Microsoft.Azure.WebJobs;
    using Microsoft.WindowsAzure.Storage.Blob;
    
    public class Functions
    {
        // output blolb sizes
        private static readonly int[] Sizes = {800, 500, 250};
    
        public static void ResizeImage(
            [BlobTrigger("input/{name}.{ext}")] Stream blobStream, string name, string ext
            , [Blob("output")] CloudBlobContainer container)
        {
            // Get the mime type to set the content type
            var mimeType = MimeMapping.GetMimeMapping($"{name}.{ext}");
            foreach (var width in Sizes)
            {
                // Set the position of the input stream to the beginning.
                blobStream.Seek(0, SeekOrigin.Begin);
    
                // Get the output stream
                var outputStream = new MemoryStream();
                ResizeImage(blobStream, outputStream, width);
    
                // Get the blob reference
                var blob = container.GetBlockBlobReference($"{name}-w{width}.{ext}");
    
                // Set the position of the output stream to the beginning.
                outputStream.Seek(0, SeekOrigin.Begin);
                blob.UploadFromStream(outputStream);
    
                // Update the content type
                blob.Properties.ContentType = mimeType;
                blob.SetProperties();
            }
        }
    
        private static void ResizeImage(Stream input, Stream output, int width)
        {
            var instructions = new Instructions
            {
                Width = width,
                Mode = FitMode.Carve,
                Scale = ScaleMode.Both
            };
            var imageJob = new ImageJob(input, output, instructions);
    
            // Do not dispose the source object
            imageJob.DisposeSourceObject = false;
            imageJob.Build();
        }
    }
    

    Note the use of the DisposeSourceObject on the ImageJob object so that we can read multiple time the blob stream.

    In addition, you should have a look at the Webjob documentation about BlobTrigger: How to use Azure blob storage with the WebJobs SDK

    The WebJobs SDK scans log files to watch for new or changed blobs. This process is not real-time; a function might not get triggered until several minutes or longer after the blob is created. In addition, storage logs are created on a "best efforts" basis; there is no guarantee that all events will be captured. Under some conditions, logs might be missed. If the speed and reliability limitations of blob triggers are not acceptable for your application, the recommended method is to create a queue message when you create the blob, and use the QueueTrigger attribute instead of the BlobTrigger attribute on the function that processes the blob.

    So it could be better to trigger message from a queue that just send the filename, you can bind automatically the input blob to the message queue :

    using System.IO;
    using System.Web;
    using ImageResizer;
    using Microsoft.Azure.WebJobs;
    using Microsoft.WindowsAzure.Storage.Blob;
    
    public class Functions
    {
        // output blolb sizes
        private static readonly int[] Sizes = { 800, 500, 250 };
    
        public static void ResizeImagesTask1(
            [QueueTrigger("newfileuploaded")] string filename,
            [Blob("input/{queueTrigger}", FileAccess.Read)] Stream blobStream,
            [Blob("output")] CloudBlobContainer container)
        {
            // Extract the filename  and the file extension
            var name = Path.GetFileNameWithoutExtension(filename);
            var ext = Path.GetExtension(filename);
    
            // Get the mime type to set the content type
            var mimeType = MimeMapping.GetMimeMapping(filename);
    
            foreach (var width in Sizes)
            {
                // Set the position of the input stream to the beginning.
                blobStream.Seek(0, SeekOrigin.Begin);
    
                // Get the output stream
                var outputStream = new MemoryStream();
                ResizeImage(blobStream, outputStream, width);
    
                // Get the blob reference
                var blob = container.GetBlockBlobReference($"{name}-w{width}.{ext}");
    
                // Set the position of the output stream to the beginning.
                outputStream.Seek(0, SeekOrigin.Begin);
                blob.UploadFromStream(outputStream);
    
                // Update the content type =>  don't know if required
                blob.Properties.ContentType = mimeType;
                blob.SetProperties();
            }
        }
    
        private static void ResizeImage(Stream input, Stream output, int width)
        {
            var instructions = new Instructions
            {
                Width = width,
                Mode = FitMode.Carve,
                Scale = ScaleMode.Both
            };
            var imageJob = new ImageJob(input, output, instructions);
    
            // Do not dispose the source object
            imageJob.DisposeSourceObject = false;
            imageJob.Build();
        }
    }
    
    0 讨论(0)
提交回复
热议问题