BlockBlobClient.UploadAsync 尝试修改传入的 WatchableReadStream 对象时失败
BlockBlobClient.UploadAsync fails when trying to modify the incoming WatchableReadStream object
我希望你能给我一些建议,因为我几乎别无选择。我想做什么:
- 通过 Azure 门户将图像上传到 blobcontainer
- 这样做时,下面的 blobtrigger 会触发。
- 我想调整作为
Microsoft.Azure.WebJobs.Host.Blobs.WatchableReadStream
对象的传入图像的大小。
- 我想将结果上传到新的 blob 容器。
问题是,当我超过任何其他 Stream
,例如MemoryStream
比未修改的 myBlob
对象 UploadAsync
方法似乎无声地失败并且 BlobTrigger
再次触发,开始无限循环。写入当前 myBlob
对象也无提示地失败。唯一有效的是在 BlockBlobClient.UploadAsync
中传递 myBlob
对象而不进行任何修改,这是无用的。我正在 Azure 中进行远程调试会话。
此外,当我尝试将 MemoryStream
对象提供给 UploadAsync
方法时,也会出现同样的问题。下面的方法是 blob 触发器:
public async Task UploadImage([BlobTrigger("mediafullsizecontainer/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, string name, ILogger log)
{
BlockBlobClient fullsizeBlobClient = _mediaFullsizeContainerClient.GetBlockBlobClient(name);
Response<BlobProperties> blobPropertiesResponse = await fullsizeBlobClient.GetPropertiesAsync(null, default);
BlobProperties blobProperties = blobPropertiesResponse.Value;
//Only process blobs when the correct metadata properties are set
if (blobProperties.Metadata.Any(property => property.Key == "category" & property.Value != String.Empty))
{
string category = blobProperties.Metadata["category"];
Stream s = await ResizeImage(myBlob);
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Response<BlobContentInfo> uploadResponse = await thumbnailBlobclient.UploadAsync(s, new BlobUploadOptions(), default);
BlobContentInfo blobContentInfo = uploadResponse.Value;
}
}
ResizeImage
方法使用 SixLabors.ImageSharp 图像处理库。
public async Task<Stream> ResizeImage(Stream inputStream)
{
(Image image, IImageFormat imageFormat) imageWithFormat = await Image.LoadWithFormatAsync(inputStream);
int height = imageWithFormat.image.Height;
int width = imageWithFormat.image.Width;
imageWithFormat.image.Mutate(operation => {
operation.Resize(width / 4, height / 4);
});
MemoryStream outputStream = new MemoryStream();
imageWithFormat.image.Save(outputStream, imageWithFormat.imageFormat);
return outputStream;
}
所以当我像这样对 myBlob
对象进行模拟更改时,myBlob.Write(buffer)
失败了:
byte[] buffer = new byte[myBlob.Length];
myBlob.Read(buffer, 0, (int)myBlob.Length);
myBlob.Position = 0;
myBlob.Write(buffer);
当我将 myBlob
内容复制到 MemoryStream
并将 memoryStream 传递给 UploadAsync
时,UploadAsync
失败:
MemoryStream ms = new MemoryStream();
myBlob.CopyTo(ms);
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Response<BlobContentInfo> uploadResponse = await thumbnailBlobclient.UploadAsync(ms, new BlobUploadOptions(), default);
唯一可行的是在不对 UploadAsync
进行任何修改的情况下传递 myBlob
对象,这是无用的,因为我需要修改传入流:
public async Task UploadImage([BlobTrigger("mediafullsizecontainer/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, string name, ILogger log)
{
BlockBlobClient fullsizeBlobClient = _mediaFullsizeContainerClient.GetBlockBlobClient(name);
Response<BlobProperties> blobPropertiesResponse = await fullsizeBlobClient.GetPropertiesAsync(null, default);
BlobProperties blobProperties = blobPropertiesResponse.Value;
//Only process blobs when the correct metadata properties are set
if (blobProperties.Metadata.Any(property => property.Key == "category" & property.Value != String.Empty))
{
string category = blobProperties.Metadata["category"];
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Response<BlobContentInfo> uploadResponse = await thumbnailBlobclient.UploadAsync(myBlob, new BlobUploadOptions(), default);
BlobContentInfo blobContentInfo = uploadResponse.Value;
}
}
如何将自定义流传递给 UploadAsync 方法? https://docs.microsoft.com/en-us/dotnet/api/azure.storage.blobs.specialized.blockblobclient.uploadasync?view=azure-dotnet 上的文档说您只需要一个流对象 - 但这是行不通的。提前致谢。
好吧,看来我自己找到了答案,我摆脱了可怕的 UploadAsync
方法,并通过将调整大小的图像的 outputStream
读入缓冲区然后打开 outputStream
来做到这一点=13=] 用于写入 thumbnailBlobclient
对象并将缓冲区传递给流对象。尝试修改触发器附带的传入 myBlob
对象,再次触发触发器并创建循环是有道理的。
Stream outputStream = await ResizeAndCropImage(myBlob);
byte[] buffer = new byte[outputStream.Length];
outputStream.Read(buffer);
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Stream s = thumbnailBlobclient.OpenWrite(true, new BlockBlobOpenWriteOptions { HttpHeaders = new BlobHttpHeaders { ContentType = "image/jpg" } }, default); //set http headers here as well?
await s.WriteAsync(buffer);
s.Close();
我将以更通用的方式设置内容类型,但这个概念很有效。
我希望你能给我一些建议,因为我几乎别无选择。我想做什么:
- 通过 Azure 门户将图像上传到 blobcontainer
- 这样做时,下面的 blobtrigger 会触发。
- 我想调整作为
Microsoft.Azure.WebJobs.Host.Blobs.WatchableReadStream
对象的传入图像的大小。 - 我想将结果上传到新的 blob 容器。
问题是,当我超过任何其他 Stream
,例如MemoryStream
比未修改的 myBlob
对象 UploadAsync
方法似乎无声地失败并且 BlobTrigger
再次触发,开始无限循环。写入当前 myBlob
对象也无提示地失败。唯一有效的是在 BlockBlobClient.UploadAsync
中传递 myBlob
对象而不进行任何修改,这是无用的。我正在 Azure 中进行远程调试会话。
此外,当我尝试将 MemoryStream
对象提供给 UploadAsync
方法时,也会出现同样的问题。下面的方法是 blob 触发器:
public async Task UploadImage([BlobTrigger("mediafullsizecontainer/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, string name, ILogger log)
{
BlockBlobClient fullsizeBlobClient = _mediaFullsizeContainerClient.GetBlockBlobClient(name);
Response<BlobProperties> blobPropertiesResponse = await fullsizeBlobClient.GetPropertiesAsync(null, default);
BlobProperties blobProperties = blobPropertiesResponse.Value;
//Only process blobs when the correct metadata properties are set
if (blobProperties.Metadata.Any(property => property.Key == "category" & property.Value != String.Empty))
{
string category = blobProperties.Metadata["category"];
Stream s = await ResizeImage(myBlob);
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Response<BlobContentInfo> uploadResponse = await thumbnailBlobclient.UploadAsync(s, new BlobUploadOptions(), default);
BlobContentInfo blobContentInfo = uploadResponse.Value;
}
}
ResizeImage
方法使用 SixLabors.ImageSharp 图像处理库。
public async Task<Stream> ResizeImage(Stream inputStream)
{
(Image image, IImageFormat imageFormat) imageWithFormat = await Image.LoadWithFormatAsync(inputStream);
int height = imageWithFormat.image.Height;
int width = imageWithFormat.image.Width;
imageWithFormat.image.Mutate(operation => {
operation.Resize(width / 4, height / 4);
});
MemoryStream outputStream = new MemoryStream();
imageWithFormat.image.Save(outputStream, imageWithFormat.imageFormat);
return outputStream;
}
所以当我像这样对 myBlob
对象进行模拟更改时,myBlob.Write(buffer)
失败了:
byte[] buffer = new byte[myBlob.Length];
myBlob.Read(buffer, 0, (int)myBlob.Length);
myBlob.Position = 0;
myBlob.Write(buffer);
当我将 myBlob
内容复制到 MemoryStream
并将 memoryStream 传递给 UploadAsync
时,UploadAsync
失败:
MemoryStream ms = new MemoryStream();
myBlob.CopyTo(ms);
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Response<BlobContentInfo> uploadResponse = await thumbnailBlobclient.UploadAsync(ms, new BlobUploadOptions(), default);
唯一可行的是在不对 UploadAsync
进行任何修改的情况下传递 myBlob
对象,这是无用的,因为我需要修改传入流:
public async Task UploadImage([BlobTrigger("mediafullsizecontainer/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, string name, ILogger log)
{
BlockBlobClient fullsizeBlobClient = _mediaFullsizeContainerClient.GetBlockBlobClient(name);
Response<BlobProperties> blobPropertiesResponse = await fullsizeBlobClient.GetPropertiesAsync(null, default);
BlobProperties blobProperties = blobPropertiesResponse.Value;
//Only process blobs when the correct metadata properties are set
if (blobProperties.Metadata.Any(property => property.Key == "category" & property.Value != String.Empty))
{
string category = blobProperties.Metadata["category"];
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Response<BlobContentInfo> uploadResponse = await thumbnailBlobclient.UploadAsync(myBlob, new BlobUploadOptions(), default);
BlobContentInfo blobContentInfo = uploadResponse.Value;
}
}
如何将自定义流传递给 UploadAsync 方法? https://docs.microsoft.com/en-us/dotnet/api/azure.storage.blobs.specialized.blockblobclient.uploadasync?view=azure-dotnet 上的文档说您只需要一个流对象 - 但这是行不通的。提前致谢。
好吧,看来我自己找到了答案,我摆脱了可怕的 UploadAsync
方法,并通过将调整大小的图像的 outputStream
读入缓冲区然后打开 outputStream
来做到这一点=13=] 用于写入 thumbnailBlobclient
对象并将缓冲区传递给流对象。尝试修改触发器附带的传入 myBlob
对象,再次触发触发器并创建循环是有道理的。
Stream outputStream = await ResizeAndCropImage(myBlob);
byte[] buffer = new byte[outputStream.Length];
outputStream.Read(buffer);
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Stream s = thumbnailBlobclient.OpenWrite(true, new BlockBlobOpenWriteOptions { HttpHeaders = new BlobHttpHeaders { ContentType = "image/jpg" } }, default); //set http headers here as well?
await s.WriteAsync(buffer);
s.Close();
我将以更通用的方式设置内容类型,但这个概念很有效。