【问题标题】:Adding an image to Azure blob storage using ASP.NET Web API fails使用 ASP.NET Web API 将图像添加到 Azure blob 存储失败
【发布时间】:2017-09-21 10:44:16
【问题描述】:

我有一个用于存储图像的 Azure blob 容器。我还有一套 ASP.NET Web API 方法,用于添加/删除/列出此容器中的 blob。如果我将图像作为文件上传,这一切都有效。但我现在想将图像作为流上传,但出现错误。

public async Task<HttpResponseMessage> AddImageStream(Stream filestream, string filename)
    {
        try
        {
            if (string.IsNullOrEmpty(filename))
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.BadRequest));
            }

            BlobStorageService service = new BlobStorageService();
            await service.UploadFileStream(filestream, filename, "image/png");
            var response = Request.CreateResponse(HttpStatusCode.OK);
            return response;
        }
        catch (Exception ex)
        {
            base.LogException(ex);
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.BadRequest));
        }

将新图像作为流添加到 blob 容器的代码如下所示。

public async Task UploadFileStream(Stream filestream, string filename, string contentType)
    {
        CloudBlockBlob blockBlobImage = this._container.GetBlockBlobReference(filename);
        blockBlobImage.Properties.ContentType = contentType;
        blockBlobImage.Metadata.Add("DateCreated", DateTime.UtcNow.ToLongDateString());
        blockBlobImage.Metadata.Add("TimeCreated", DateTime.UtcNow.ToLongTimeString());
        await blockBlobImage.UploadFromStreamAsync(filestream);
    }

最后这是我失败的单元测试。

[TestMethod]
    public async Task DeployedImageStreamTests()
    {
        string blobname = Guid.NewGuid().ToString();

        //Arrange
        MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes($"This is a blob called {blobname}."))
        {
            Position = 0
        };

        string url = $"http://mywebapi/api/imagesstream?filestream={stream}&filename={blobname}";
        Console.WriteLine($"DeployedImagesTests URL {url}");
        HttpContent content = new StringContent(blobname, Encoding.UTF8, "application/json");
        var response = await ImagesControllerPostDeploymentTests.PostData(url, content);

        //Assert
        Assert.IsNotNull(response);
        Assert.IsTrue(response.IsSuccessStatusCode); //fails here!!
        Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
    }

我得到的错误是 值不能为空。 参数名称:来源

这是使用 Web API 将图像流上传到 Azure blob 存储的正确方法吗?我可以毫无问题地处理图像文件,并且现在我正在尝试使用流上传时才遇到这个问题。

【问题讨论】:

  • 您遇到的错误的堆栈跟踪是什么(即,哪一行代码引发了错误)?

标签: c# asp.net azure asp.net-web-api azure-blob-storage


【解决方案1】:

这是使用 Web API 将图像流上传到 Azure blob 存储的正确方法吗?我可以毫无问题地处理图像文件,而现在我正在尝试使用流上传时才遇到这个问题。

根据您的描述和错误消息,我发现您将您的 url 中的流数据发送到 web api。

根据这篇文章:

Web API 使用以下规则绑定参数:

如果参数是“简单”类型,Web API 会尝试从 URI 中获取值。简单类型包括 .NET 基本类型(int、bool、double 等),加上 TimeSpan、DateTime、Guid、decimal 和 string,以及任何具有可以从字符串转换的类型转换器的类型。 (稍后会详细介绍类型转换器。)

对于复杂类型,Web API 尝试使用媒体类型格式化程序从消息正文中读取值。

在我看来,流是一种复杂的类型,所以我建议你可以将它作为正文发布到 web api。

另外,我建议您可以创建一个文件类并使用 Newtonsoft.Json 将其转换为 json 作为消息的内容。

更多细节,你可以参考下面的代码。 文件类:

  public class file
    {
        //Since JsonConvert.SerializeObject couldn't serialize the stream object I used byte[] instead
        public byte[] str { get; set; }
        public string filename { get; set; }

        public string contentType { get; set; }
    }

网页接口:

  [Route("api/serious/updtTM")]
    [HttpPost]
    public void updtTM([FromBody]file imagefile)
    {
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse("aaaaa");
            var client = storageAccount.CreateCloudBlobClient();
            var container = client.GetContainerReference("images");

            CloudBlockBlob blockBlobImage = container.GetBlockBlobReference(imagefile.filename);
            blockBlobImage.Properties.ContentType = imagefile.contentType;
            blockBlobImage.Metadata.Add("DateCreated", DateTime.UtcNow.ToLongDateString());
            blockBlobImage.Metadata.Add("TimeCreated", DateTime.UtcNow.ToLongTimeString());

            MemoryStream stream = new MemoryStream(imagefile.str)
            {
                Position=0
            };
            blockBlobImage.UploadFromStreamAsync(stream);
        }

测试控制台:

 using (var client = new HttpClient())
            {
                string URI = string.Format("http://localhost:14456/api/serious/updtTM");
                file f1 = new file();

                byte[] aa = File.ReadAllBytes(@"D:\Capture2.PNG");

                f1.str = aa;
                f1.filename = "Capture2";
                f1.contentType = "PNG";
                var serializedProduct = JsonConvert.SerializeObject(f1); 
                var content = new StringContent(serializedProduct, Encoding.UTF8, "application/json");
                var result = client.PostAsync(URI, content).Result;
            }

【讨论】:

  • 这是有道理的。我会试一试,看看它是否能解决问题。感谢您的信息。
  • 我最初在将流转换为 JSON 时遇到了问题,但我设法解决了这个问题。此解决方案现在有效,因此我将其标记为已接受的答案。
猜你喜欢
  • 2018-10-29
  • 2014-05-22
  • 2016-08-15
  • 2018-09-02
  • 2019-06-27
  • 1970-01-01
  • 1970-01-01
  • 2020-01-09
  • 2014-07-22
相关资源
最近更新 更多