Azure WebJobs Blob 触发器 - 多次调整大小
Azure WebJobs Blob Trigger - multiple resizes
我正在尝试创建 C# Azure WebJob,它在创建新的 Blob 时触发,以将上传的图像调整为三种不同的大小。我发现并关注了这个很棒的 tutorial.
有两个部分,第一部分 "works" 但进入递归循环,因为创建三个新尺寸会触发脚本,该脚本会为三个新图像中的每一个创建另外三个实例,依此类推等等。这是故意的,以强调最终实施的必要性。
这是 "works" 在 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 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();
}
}
}
我猜示例使用了 ImageResizer NuGet 包。
您可以使用以下命令从 VS2015 安装它
安装包 ImageResizer。
那么如果你添加
使用 ImageResizer.ExtensionMethods;
在您的代码中,您将获得扩展 Stream 对象的 CopyToBytes 方法。
希望这可以帮助
最好的祝福
斯蒂芬
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();
}
}
注意在 ImageJob
对象上使用 DisposeSourceObject
以便我们可以多次读取 blob 流。
此外,您应该查看有关 BlobTrigger
的 Webjob 文档: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.
因此最好从只发送文件名的队列中触发消息,您可以将输入 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();
}
}
我用 VS2015 创建了一个 Webjob 项目(还在 update1),我使用的是 Azure 2.8 SDK(我很快会更新到 2.9)。
我已经使用您原始 link 中的示例代码进行了剪切和粘贴。
我已经添加了两个应用程序配置连接字符串(并在应用程序设置中更新了 Web 应用程序对应的连接字符串)。
我刚刚添加了引用的块包和缺少的 "using"。
它工作正常。
我已经在 GitHub 上发布了示例代码,以供您试用。
https://github.com/stephgou/ImageResizer.git
您只需更新应用配置和网络应用连接字符串。
希望对您有所帮助
此致
斯蒂芬
我正在尝试创建 C# Azure WebJob,它在创建新的 Blob 时触发,以将上传的图像调整为三种不同的大小。我发现并关注了这个很棒的 tutorial.
有两个部分,第一部分 "works" 但进入递归循环,因为创建三个新尺寸会触发脚本,该脚本会为三个新图像中的每一个创建另外三个实例,依此类推等等。这是故意的,以强调最终实施的必要性。
这是 "works" 在 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 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();
}
}
}
我猜示例使用了 ImageResizer NuGet 包。 您可以使用以下命令从 VS2015 安装它 安装包 ImageResizer。 那么如果你添加 使用 ImageResizer.ExtensionMethods; 在您的代码中,您将获得扩展 Stream 对象的 CopyToBytes 方法。 希望这可以帮助 最好的祝福 斯蒂芬
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();
}
}
注意在 ImageJob
对象上使用 DisposeSourceObject
以便我们可以多次读取 blob 流。
此外,您应该查看有关 BlobTrigger
的 Webjob 文档: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.
因此最好从只发送文件名的队列中触发消息,您可以将输入 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();
}
}
我用 VS2015 创建了一个 Webjob 项目(还在 update1),我使用的是 Azure 2.8 SDK(我很快会更新到 2.9)。
我已经使用您原始 link 中的示例代码进行了剪切和粘贴。 我已经添加了两个应用程序配置连接字符串(并在应用程序设置中更新了 Web 应用程序对应的连接字符串)。 我刚刚添加了引用的块包和缺少的 "using"。 它工作正常。
我已经在 GitHub 上发布了示例代码,以供您试用。
https://github.com/stephgou/ImageResizer.git
您只需更新应用配置和网络应用连接字符串。
希望对您有所帮助
此致 斯蒂芬