使用 ASP.NET Web API 将图像添加到 Azure blob 存储失败
Adding an image to Azure blob storage using ASP.NET Web API fails
我有一个用于存储图像的 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);
}
我得到的错误是值不能为空。
参数名称:source
这是使用 Web API 将图像流上传到 Azure blob 存储的正确方法吗?我可以毫无问题地处理图像文件,现在我正在尝试使用流上传时才遇到这个问题。
Is this the correct way to upload an image stream to Azure blob storage using Web API? I have it working with image files without a problem, and only getting this problem now that I'm trying to upload using streams.
根据您的描述和错误信息,我发现您将 url 中的流数据发送到网络 api。
根据这篇文章:
Web API 使用以下规则绑定参数:
如果参数是 "simple" 类型,Web API 会尝试从 URI 中获取值。简单类型包括 .NET 基元类型(int、bool、double 等),加上 TimeSpan、DateTime、Guid、decimal 和 string,以及任何具有可以从字符串转换的类型转换器的类型。 (稍后会详细介绍类型转换器。)
对于复杂类型,Web API 尝试使用媒体类型格式化程序从消息正文中读取值。
在我看来,流是一种复杂的类型,因此我建议您可以 post 将其作为正文发送到网络 api。
此外,我建议您可以创建一个文件 class 并使用 Newtonsoft.Json 将其转换为 json 作为消息的内容。
更多细节,您可以参考下面的代码。
文件 class:
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; }
}
网页Api:
[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;
}
我有一个用于存储图像的 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);
}
我得到的错误是值不能为空。 参数名称:source
这是使用 Web API 将图像流上传到 Azure blob 存储的正确方法吗?我可以毫无问题地处理图像文件,现在我正在尝试使用流上传时才遇到这个问题。
Is this the correct way to upload an image stream to Azure blob storage using Web API? I have it working with image files without a problem, and only getting this problem now that I'm trying to upload using streams.
根据您的描述和错误信息,我发现您将 url 中的流数据发送到网络 api。
根据这篇文章:
Web API 使用以下规则绑定参数:
如果参数是 "simple" 类型,Web API 会尝试从 URI 中获取值。简单类型包括 .NET 基元类型(int、bool、double 等),加上 TimeSpan、DateTime、Guid、decimal 和 string,以及任何具有可以从字符串转换的类型转换器的类型。 (稍后会详细介绍类型转换器。)
对于复杂类型,Web API 尝试使用媒体类型格式化程序从消息正文中读取值。
在我看来,流是一种复杂的类型,因此我建议您可以 post 将其作为正文发送到网络 api。
此外,我建议您可以创建一个文件 class 并使用 Newtonsoft.Json 将其转换为 json 作为消息的内容。
更多细节,您可以参考下面的代码。 文件 class:
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; }
}
网页Api:
[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;
}