Azure WebJobs Blob触发器 - 多个调整大小

时间:2016-04-26 15:16:54

标签: c# azure azure-storage azure-webjobs azure-blob-storage

我试图创建C#Azure WebJob,它是在新的Blob创建时触发的,用于将上传的图像调整为三种不同的大小。我找到并关注了这个伟大的tutorial

有两个部分,第一部分"工作"但是进入一个递归循环,因为三个新尺寸的创建触发了脚本,这为三个新图像中的每一个创建了三个实例,依此类推。这是故意的,强调最终实施的必要性。

这是"工作的初始递归循环代码"在functions.cs文件中的位置:

public static void ResizeImagesW800([BlobTrigger("input/{name}.{ext}")] Stream input,
    [Blob("output/{name}-w800.{ext}", FileAccess.Write)] Stream output)
{
    ResizeImage(input, output, 800);
}

public static void ResizeImagesW500([BlobTrigger("input/{name}.{ext}")] Stream input,
    [Blob("output/{name}-w500.{ext}", FileAccess.Write)] Stream output)
{
    ResizeImage(input, output, 500);
}

private static void ResizeImage(Stream input, Stream output, int width)
{
    var instructions = new Instructions
    {
        Width = width,
        Mode = FitMode.Carve,
        Scale = ScaleMode.Both
    };
    ImageBuilder.Current.Build(new ImageJob(input, output, instructions));
}

以下是Visual Studio 2015发出错误的代码:

public static void ResizeImagesTask(
    [BlobTrigger("input/{name}.{ext}")] Stream inputBlob,
    string name,
    string ext,
    IBinder binder)
{
    int[] sizes = { 800, 500, 250 };
    var inputBytes = inputBlob.CopyToBytes();
    foreach (var width in sizes)
    {
        var input = new MemoryStream(inputBytes);
        var output = binder.Bind<Stream>(new BlobAttribute($"output/{name}-w{width}.{ext}", FileAccess.Write));

        ResizeImage(input, output, width);
    }
}

private static void ResizeImage(Stream input, Stream output, int width)
{
    var instructions = new Instructions
    {
        Width = width,
        Mode = FitMode.Carve,
        Scale = ScaleMode.Both
    };
    ImageBuilder.Current.Build(new ImageJob(input, output, instructions));
}

此行引发错误:

 var inputBytes = inputBlob.CopyToBytes();

错误是:

CS1061: 'Stream' does not contain a definition for 'CopyToBytes' and no extension method 'CopyToBytes' accepting a first argument of type 'Stream' could be found (are you missing a using directive or an assembly reference?)

我尝试使用.NET 3.5,4.0,4.5,4.5.1,4.5.2,4.6,4.6.1作为目标框架,但所有这些都会产生同样的错误。

此外,这里是Functions.cs文件的using语句:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.WindowsAzure.Storage;
using ImageResizer;

我在这里做错了什么?谢谢!

更新1

using System;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.WindowsAzure.Storage;
using ImageResizer;
using ImageResizer.ExtensionMethods;
using Microsoft.WindowsAzure.Storage.Blob;

namespace HilcoIndustrialAssetApiWebJob
{
    public class Functions
    {
        // output blolb sizes
        private static readonly int[] Sizes = { 800, 500, 250 };

        public static void ResizeImagesTask(
        [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);

            Console.WriteLine("New Blob name -> " + name);

            // 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}_{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();
        }
    }
}

3 个答案:

答案 0 :(得分:2)

我猜这个示例使用的是ImageResizer NuGet包。 您可以使用该命令从VS2015安装它       安装包ImageResizer。 然后,如果你添加       使用ImageResizer.ExtensionMethods; 在您的代码中,您将获得扩展Stream对象的CopyToBytes方法。 希望这可以帮助 最好的祝福 斯特凡

答案 1 :(得分:0)

Azure Webjob SDK支持Blob绑定,以便您可以直接绑定到blob。

在您的上下文中,您希望绑定到输入blob并创建多个输出blob。

  • 使用BlobTriggerAttribute作为输入。
  • 使用BlobTriggerAttribute绑定到输出blob。因为您想要创建多个输出blob,所以可以直接绑定到输出容器。

您触发的功能的代码可能如下所示:

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

请注意在DisposeSourceObject对象上使用ImageJob,以便我们可以多次读取blob流。

此外,您应该查看有关BlobTrigger的Webjob文档:How to use Azure blob storage with the WebJobs SDK

  

WebJobs SDK扫描日志文件以监视新的或更改的blob。这个过程不是实时的;在创建blob后几分钟或更长时间内,函数可能不会被触发。另外,storage logs are created on a "best efforts"基础;无法保证将捕获所有事件。在某些情况下,可能会错过日志。如果blob触发器的速度和可靠性限制对于您的应用程序是不可接受的,建议的方法是在创建blob时创建队列消息,并使用QueueTrigger属性而不是BlobTrigger属性处理blob的函数。

因此,从发送文件名的队列中触发消息可能会更好,您可以自动将输入blob绑定到消息队列:

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

答案 2 :(得分:0)

我用VS2015创建了一个Webjob项目(仍然在update1中),我正在使用Azure 2.8 SDK(我很快会将其更新为2.9)。

我做过切割&amp;粘贴原始链接中的示例代码。 我添加了两个app config连接字符串(并在Application Settings中更新了Web App对应的连接字符串)。 我有juste添加了引用的nugget包和缺少的“using”。 它工作正常。

我已经在GitHub上发布了示例代码,以备您尝试使用。

https://github.com/stephgou/ImageResizer.git

您只需更新应用配置和您的网络应用连接字符串。

希望这有帮助

祝你好运 斯特凡