使用 WebImage Class 在 asp.net webapi 中上传图像
Upload Image in asp.net webapi using WebImage Class
我想为我的 webapi 项目上传一个图像,我在 Asp.net MVC 4 中使用 WebImage class 来保存、裁剪、旋转图像通过使用这个 class.
我在 ApiController 中包含 WebHelper,其功能与 mvc 项目相同
我的问题是在 webapi 项目中,当我在 Webapi 控制器中上传图像时,我收到一个错误:
{
Message: "An error has occurred."
ExceptionMessage: "No MediaTypeFormatter is available to read an object of type 'WebImage' from content with media type 'multipart/form-data'."
ExceptionType: "System.InvalidOperationException"
StackTrace: " at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) at System.Web.Http.Controllers.HttpActionBinding.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(HttpParameterBinding parameterBinder) at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() at System.Threading.Tasks.TaskHelpers.IterateImpl(IEnumerator`1 enumerator, CancellationToken cancellationToken)"
}
和我的上传方法示例:
[HttpPost]
public HttpResponseMessage filer(WebImage data)
{
HttpResponseMessage response = null;
if (data == null)
{
response = new HttpResponseMessage()
{
Content = new StringContent("Not a image file"),
StatusCode = HttpStatusCode.BadRequest
};
}
else {
response = new HttpResponseMessage()
{
Content = new StringContent(data.FileName.ToString()),
StatusCode = HttpStatusCode.OK
};
}
return response;
}
请解释如何添加 MediaTypeFormatter 以支持 WebImage class。
有两种不使用 MediaFormatter 的方法,这些方法涉及创建自定义 ModelBinder 或实现接受 base64 编码字符串或字节数组以接受数据的模型 class,然后将来自该模型 class 的数据到 WebImage。但是要回答这个问题,过程非常简单。这是一种实现方式。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Formatting;
using System.Web;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Helpers;
using System.Net.Http.Headers;
using System.IO;
using System.Net.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text;
using System.Diagnostics;
namespace WhosebugWI.Infrastructure
{
public class WebImageMediaFormatter : MediaTypeFormatter
{
public WebImageMediaFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
}
public override bool CanReadType(Type type)
{
return type == typeof(WebImage);
}
public override bool CanWriteType(Type type)
{
return false;
}
public async override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
{
byte[] buffer = new byte[content.Headers.ContentLength.Value];
while (await readStream.ReadAsync(buffer, (int)readStream.Position, buffer.Length - (int) readStream.Position) > 0) { }
string stringData = Encoding.Default.GetString(buffer);
JObject myJson = JObject.Parse(stringData);
JToken myJToken = myJson.GetValue("imageBytes");
byte[] myBytes = myJToken.Values().Select(x => (byte)x).ToArray();
return new WebImage(myBytes);
}
}
}
您必须在 IIS 托管应用程序的 HttpConfiguration 对象格式化程序集合的实例中注册 mediaformatter,这将在 WebApiConfig.Register 方法中。
config.Formatters.Insert(0, new WebImageMediaFormatter());
我认为这是一个有趣的问题,所以进行了一个实现,为了完整起见,我包含了一些 javascript 代码:
var ajaxCall = function (data) {
dataString = data.toString();
dataString = "[" + dataString + "]";
dataString = JSON.parse(dataString);
console.log(dataString.length);
//console.log(dataString);
var imageData = {};
imageData.imageBytes = dataString;
console.log(imageData);
//console.log(imageData);
var ajaxOptions = {};
ajaxOptions.url = "/api/image/PostWebImage";
ajaxOptions.type = "Post";
ajaxOptions.contentType = "application/json";
ajaxOptions.data = JSON.stringify(imageData);
ajaxOptions.success = function () {
console.log('no error detected');
};
ajaxOptions.error = function (jqXHR) {
console.log(jqXHR);
};
$.ajax(ajaxOptions);
};
var postImage = function () {
var file = $('input[type=file]')[0].files[0];
var myfilereader = new FileReader();
myfilereader.onloadend = function () {
var uInt8Array = new Uint8Array(myfilereader.result);
ajaxCall(uInt8Array);
}
if (file) {
myfilereader.readAsArrayBuffer(file);
} else {
console.log("failed to read file");
}
};
还要记住该网站中的硬编码限制 api 接受有限数量的数据,除非您修改 web.config 文件以修改 httpRuntime 环境以接受大量请求。 (这是假设您不将上传缓冲成块,这将是更好的方法)。
<httpRuntime targetFramework="4.5" maxRequestLength="1024000" />
最后,不需要如上所述的媒体格式化程序的替代解决方案是创建一个模型 class,其中 public 属性 在发送数据时接受数据。
namespace WhosebugWI.Models
{
public class myModel
{
public byte [] imageBytes { get; set; }
}
}
然后您可以在操作方法中创建对象。
public IHttpActionResult Post( myModel imageData )
{
WebImage myWI = new WebImage(imageData.imageBytes);
string path = System.Web.Hosting.HostingEnvironment.MapPath("~/Images/somefile.png");
myWI.Save(path);
return Ok();
}
为了将来参考,请记住 Web api 中的默认模型活页夹实现不接受任何 class 作为没有无参数构造函数的操作方法中的参数。此规则的唯一例外是使用依赖注入插件(例如 ninject 或 unity)进行依赖注入时。
我想为我的 webapi 项目上传一个图像,我在 Asp.net MVC 4 中使用 WebImage class 来保存、裁剪、旋转图像通过使用这个 class.
我在 ApiController 中包含 WebHelper,其功能与 mvc 项目相同 我的问题是在 webapi 项目中,当我在 Webapi 控制器中上传图像时,我收到一个错误:
{
Message: "An error has occurred."
ExceptionMessage: "No MediaTypeFormatter is available to read an object of type 'WebImage' from content with media type 'multipart/form-data'."
ExceptionType: "System.InvalidOperationException"
StackTrace: " at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) at System.Web.Http.Controllers.HttpActionBinding.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(HttpParameterBinding parameterBinder) at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() at System.Threading.Tasks.TaskHelpers.IterateImpl(IEnumerator`1 enumerator, CancellationToken cancellationToken)"
}
和我的上传方法示例:
[HttpPost]
public HttpResponseMessage filer(WebImage data)
{
HttpResponseMessage response = null;
if (data == null)
{
response = new HttpResponseMessage()
{
Content = new StringContent("Not a image file"),
StatusCode = HttpStatusCode.BadRequest
};
}
else {
response = new HttpResponseMessage()
{
Content = new StringContent(data.FileName.ToString()),
StatusCode = HttpStatusCode.OK
};
}
return response;
}
请解释如何添加 MediaTypeFormatter 以支持 WebImage class。
有两种不使用 MediaFormatter 的方法,这些方法涉及创建自定义 ModelBinder 或实现接受 base64 编码字符串或字节数组以接受数据的模型 class,然后将来自该模型 class 的数据到 WebImage。但是要回答这个问题,过程非常简单。这是一种实现方式。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Formatting;
using System.Web;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Helpers;
using System.Net.Http.Headers;
using System.IO;
using System.Net.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text;
using System.Diagnostics;
namespace WhosebugWI.Infrastructure
{
public class WebImageMediaFormatter : MediaTypeFormatter
{
public WebImageMediaFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
}
public override bool CanReadType(Type type)
{
return type == typeof(WebImage);
}
public override bool CanWriteType(Type type)
{
return false;
}
public async override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
{
byte[] buffer = new byte[content.Headers.ContentLength.Value];
while (await readStream.ReadAsync(buffer, (int)readStream.Position, buffer.Length - (int) readStream.Position) > 0) { }
string stringData = Encoding.Default.GetString(buffer);
JObject myJson = JObject.Parse(stringData);
JToken myJToken = myJson.GetValue("imageBytes");
byte[] myBytes = myJToken.Values().Select(x => (byte)x).ToArray();
return new WebImage(myBytes);
}
}
}
您必须在 IIS 托管应用程序的 HttpConfiguration 对象格式化程序集合的实例中注册 mediaformatter,这将在 WebApiConfig.Register 方法中。
config.Formatters.Insert(0, new WebImageMediaFormatter());
我认为这是一个有趣的问题,所以进行了一个实现,为了完整起见,我包含了一些 javascript 代码:
var ajaxCall = function (data) {
dataString = data.toString();
dataString = "[" + dataString + "]";
dataString = JSON.parse(dataString);
console.log(dataString.length);
//console.log(dataString);
var imageData = {};
imageData.imageBytes = dataString;
console.log(imageData);
//console.log(imageData);
var ajaxOptions = {};
ajaxOptions.url = "/api/image/PostWebImage";
ajaxOptions.type = "Post";
ajaxOptions.contentType = "application/json";
ajaxOptions.data = JSON.stringify(imageData);
ajaxOptions.success = function () {
console.log('no error detected');
};
ajaxOptions.error = function (jqXHR) {
console.log(jqXHR);
};
$.ajax(ajaxOptions);
};
var postImage = function () {
var file = $('input[type=file]')[0].files[0];
var myfilereader = new FileReader();
myfilereader.onloadend = function () {
var uInt8Array = new Uint8Array(myfilereader.result);
ajaxCall(uInt8Array);
}
if (file) {
myfilereader.readAsArrayBuffer(file);
} else {
console.log("failed to read file");
}
};
还要记住该网站中的硬编码限制 api 接受有限数量的数据,除非您修改 web.config 文件以修改 httpRuntime 环境以接受大量请求。 (这是假设您不将上传缓冲成块,这将是更好的方法)。
<httpRuntime targetFramework="4.5" maxRequestLength="1024000" />
最后,不需要如上所述的媒体格式化程序的替代解决方案是创建一个模型 class,其中 public 属性 在发送数据时接受数据。
namespace WhosebugWI.Models
{
public class myModel
{
public byte [] imageBytes { get; set; }
}
}
然后您可以在操作方法中创建对象。
public IHttpActionResult Post( myModel imageData )
{
WebImage myWI = new WebImage(imageData.imageBytes);
string path = System.Web.Hosting.HostingEnvironment.MapPath("~/Images/somefile.png");
myWI.Save(path);
return Ok();
}
为了将来参考,请记住 Web api 中的默认模型活页夹实现不接受任何 class 作为没有无参数构造函数的操作方法中的参数。此规则的唯一例外是使用依赖注入插件(例如 ninject 或 unity)进行依赖注入时。