首页 > 解决方案 > 尝试修改传入的 WatchableReadStream 对象时,BlockBlobClient.UploadAsync 失败

问题描述

我希望你有一些建议,因为我几乎没有选择。我正在尝试做的事情:

问题是,当我传递任何其他Stream的,例如 aMemoryStream而不是未修改的myBlob对象时,该UploadAsync方法似乎默默地失败并BlobTrigger再次触发,开始一个无限循环。写入当前myBlob对象也会静默失败。唯一有效的方法是在没有任何修改的情况下传递myBlob对象,这是无用的。BlockBlobClient.UploadAsync我正在 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内容复制到 aMemoryStream并将 memoryStream 传递给 时UploadAsyncUploadAsync失败:

                MemoryStream ms = new MemoryStream();
                myBlob.CopyTo(ms);
                 
                BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
                Response<BlobContentInfo> uploadResponse = await thumbnailBlobclient.UploadAsync(ms, new BlobUploadOptions(), default);

唯一有效的是传递myBlob对象而不进行任何修改,UploadAsync因为我需要修改传入流:

        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上的文档说您只需要一个流对象-但这并不工作。提前致谢。

标签: azureuploadblob

解决方案


好的,看起来我自己找到了答案,我摆脱了可怕的UploadAsync方法,并通过outputStream将调整大小的图像读入缓冲区然后打开一个Stream用于写入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();

我将以更通用的方式设置内容类型,但这个概念是有效的。


推荐阅读