使用ImageResizer的Azure C#WebJob未正确设置Content-Type
我正在使用Azure WebJob来调整新上传的图像的大小。 resize有效,但新创建的图像没有在Blob存储中正确设置其内容类型。 相反,它们列在application / octet-stream中。 这里处理resize的代码:
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(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)); }
我的问题是我在哪里以及如何设置内容类型? 这是我必须手动完成的,或者我是如何使用库来防止它分配与原始内容类型相同的内容类型(库表示应该展示的行为)?
谢谢!
最终更新
感谢Thomas在最终解决方案方面提供的帮助,请点击此处!
public class Functions { // output blolb sizes private static readonly int[] Sizes = { 800, 500, 250 }; public static void ResizeImagesTask( [QueueTrigger("assetimage")] AssetImage asset, string container, string name, string ext, [Blob("{container}/{name}_master.{ext}", FileAccess.Read)] Stream blobStream, [Blob("{container}")] CloudBlobContainer cloudContainer) { // Get the mime type to set the content type var mimeType = MimeMapping.GetMimeMapping($"{name}_master.{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 = cloudContainer.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(); } public static void PoisonErrorHandler([QueueTrigger("webjobs-blogtrigger-poison")] BlobTriggerPosionMessage message, TextWriter log) { log.Write("This blob couldn't be processed by the original function: " + message.BlobName); } } public class AssetImage { public string Container { get; set; } public string Name { get; set; } public string Ext { get; set; } } public class BlobTriggerPosionMessage { public string FunctionId { get; set; } public string BlobType { get; set; } public string ContainerName { get; set; } public string BlobName { get; set; } public string ETag { get; set; } }
您无法从实施中设置内容类型:
您需要访问CloudBlockBlob.Properties.ContentType
属性:
CloudBlockBlob blob = new CloudBlockBlob(...); blob.Properties.ContentType = "image/..."; blob.SetProperties();
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文档: 如何使用WebJobs SDK使用Azure blob存储
WebJobs SDK扫描日志文件以监视新的或更改的blob。 这个过程不是实时的; 在创建blob后几分钟或更长时间内,函数可能不会被触发。 此外, 存储日志是在“尽力而为”的基础上创建的; 无法保证将捕获所有事件。 在某些情况下,可能会错过日志。 如果blob触发器的速度和可靠性限制对于您的应用程序是不可接受的,建议的方法是在创建blob时创建队列消息,并在处理blob的函数上使用QueueTrigger属性而不是
BlobTrigger
属性。
因此,从发送文件名的队列中触发消息可能更好,您可以自动将输入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(); } }
- ASP.NET Web API和OpenID Connect:如何从授权代码获取访问令牌
- 在ASP.NET Core 2.0中从另一个(无用户交互)授权一个应用程序服务
- 如何从azure表存储查询中获取超过1000个实体?
- 使用AzureReader2插件的Azure ImageResizer没有resize
- 无法从Azure AD获取承载令牌以与API App一起使用
- Azure Active Directory回复URL未按预期工作
- PUT和Delete不能与Windows Azure上的ASP.NET WebAPI和数据库一起使用
- DocumentDB中每个集合的单个或多个实体
- OAuth2资源所有者密码通过API授予