WebJobs is a feature of the Azure App Service that enables you to run a program or a script, continuously, either based on a specific schedule or on demand, in the same context as a web app, API app, or mobile app.

WebJobs SDK provides triggers, which comprise the conditions that cause the function to be called, and binders, that comprise the way of acquiring information into and out of method parameters.

In this tutorial, we are going to use:

  • the `BlobTrigger` attribute, that triggers a process whenever a new blob is created in an Azure Storage account,
  • the `IBinder` interface, to alter the name of the resized image based on each new width.
  • the ImageResizer library, which, except from resizing any image, provides as well many options for image manipulation and optimization.

Create an Azure WebJobs project

create_azure_web_job_project

Please note that as .NET framework 4.6.1 is not supported yet in Azure, you should select a target framework less than 4.6.1. I would recommend to use 4.5.2 for this tutorial.

Update NuGet Packages

You should update NuGet packages by running the following command in the package manager console:

`PM> update-package`

Install ImageResizer NuGet Package

imageresizer_nuget_package

Specify Azure Storage Account to use

In your `App.config` settings file, please specify the connection strings of the storage account you are going to use. The reason why there are two options is that:

  • `AzureWebJobsDashboard` is used for generated logs for your webjobs, while

  • `AzureWebJobsStorage` provides connection strings to the storage account where your data is actually stored.

WebJobs to resize your images

What we want in this scenario is, every time a new image is uploaded in our `input` container, to have new scaled images stored in the `output` container. The image will be scaled to two different width sizes `800 and 500`.

Now, in order to do this you have two options:

  • either to use multiple WebJobs, each one of which creates the appropriate scaled image, or
  • a single WebJob to create different sizes in a single call.

Multiple WebJobs for each size

We update `Functions.cs` using two methods that will scale each newly uploaded file to `800px` and `500px` in width.

public class Functions
{
    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));
    }
}

Let’s explain the code a little bit.

  • The first parameter, `BlobTrigger`, is an attribute which creates a trigger so that, when a new file is uploaded in the `input` container, this method runs and performs its task.
  • The second parameter, `Blob`, sets out that the output stream will be stored in the `output` container and that the new file will have the name (`{name}`) and extension  (`{ext}`) of the input file, plus the width that the image will be scaled into.
  • The `ResizeImage` performs the actual task; it takes a source stream, an output stream and some instructions to scale the input image.

Single WebJob, multiple output files

Now, in order to achieve this, it gets a bit trickier. This is because, when using a `Blob` attribute, as in the first example, you can alter the name only for the first input blob, plus the input stream is closed after the first scale.

To overcome these issues, you need to make some slight modifications:

  • Get the bytes from the input stream of the `Blob` that triggered the method and copy them to a `MemoryStream` every time a resizing task is started.
  • Use `IBinder` to create a new `Stream`, as output stream, and specify a new `BlobAttribute` to generate a new name for the scaled image.
  • The `string name` and the `string ext` derive from the deserialized message that holds information about the input blob and that is used to trigger the WebJob.
public class Functions
{
    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));
    }
}

Please note that for code clarity, `using` statements for `MemoryStream` are not used.

Publish in Azure

In the visual studio solutions explorer, right-click and select the “Publish As Azure WebJob…” option.

publish_webjobs

Select Run Continuously

webjobs_run_continuously

Monitor your WebJob

In our example,  the WebJob was deployed in a WebJobsImageResizer Azure WebApp.

webjobs_azure_dashboard

You can monitor and see the details of your WebJob through the Kudu dashboard, by accessing the Kudu service for the web app where you have deployed your WebJob, from https://webjobsimageresizer.scm.azurewebsites.net url.

From Tools, select the WebJobs Dashboard

webjobs_kudu

Now, you can view all available WebJobs available in your web app.

webJobs_functions

When you upload a file in the `input` container, you can see that the WebJob is triggered properly and new scaled images are generated. This info is available by clicking on the name of the WebJobs function.

webjobs_invocation_details

And your files are properly stored in your `output` container.

azure_storage_explorer_output_container

 

 

Categorized in:

Tagged in:

,