BlockBlobClient.UploadAsync 尝试修改传入的 WatchableReadStream 对象时失败

BlockBlobClient.UploadAsync fails when trying to modify the incoming WatchableReadStream object

我希望你能给我一些建议,因为我几乎别无选择。我想做什么:

问题是,当我超过任何其他 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();

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