本文介绍了使用WebImage类在asp.net的WebAPI上传图片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要上传图片为我的WebAPI项目,我使用WebImage类的 Asp.net MVC 4 作为保存,剪裁,使用这个类旋转图像。

I want to upload an Image for my webapi project and i am using WebImage class in Asp.net MVC 4 for Saving, cropping, rotating image by using this class.

我包括在WebHelper与ApiController像MVC项目相同的功能
我的问题是在项目的WebAPI是,当我上传的WebAPI控制器的图像我收到一个错误:

I include WebHelper in ApiController with same functionality like mvc projectMy problem is in webapi project is when i upload image in Webapi controller i receive an error :

    {
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类。

Please Explain me how to add MediaTypeFormatter to support WebImage class.

推荐答案

有涉及不使用MediaFormatter两种方法,这涉及创建一个自定义的模型绑定器或执行一个接受的base64连接codeD字符串的模型类或字节数组来接受数据,然后从该模型类的转换数据成WebImage。然而,要回答这个问题,这个过程是非常简单的。这是一个实现。

There are two approaches that involve not using a MediaFormatter, these would involve creating a custom ModelBinder or implementing an model class that accepts a base64 encoded string or a byte array to accept the data, then converting the data from that model class into a WebImage. However to answer the question, the process is very straightforward. Here is one implementation.

 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 StackOverFlowWI.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);
         }
     }
 }

您必须注册在HttpConfiguration对象格式化集合中的实例mediaformatter一个IIS托管的应用程序,这将是在WebApiConfig.Register方法​​。

You have to register the mediaformatter in the instance of the HttpConfiguration object formatters collection in an IIS hosted application this would be in the WebApiConfig.Register method.

        config.Formatters.Insert(0, new WebImageMediaFormatter());

我认为这是一个有趣的问题,以便通过一个实现了和我,包括一些JavaScript code对完整性的考虑:

I thought this was an interesting question so went through an implementation and am including some javascript code for the sake of completeness:

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");
        }
    };

也请记住,除非你修改web.config文件来修改的httpRuntime环境中接受大量的请求在网页API硬codeD限制接收的数据量有限。 (这是假设你没有缓冲上传大块这将是一个更好的办法)。

Also keep in mind the hard coded limit in that web api accepts a limited amount of data unless you modify the web.config file to modify the httpRuntime environment to accept large requests. (This is assuming that you do not buffer the upload into chunks which would be a better approach).

<httpRuntime targetFramework="4.5" maxRequestLength="1024000" />

最后,将不需要上述一个mediaformatter将创建一个,因为它被发送,接受数据的公共属性模型类的替代解决方案。

Finally an alternate solution that would not require a mediaformatter as mentioned above would be to create a model class with a public property that accepts the data as it is sent.

namespace StackOverFlowWI.Models
{
     public class myModel
    {
        public byte [] imageBytes { get; set; }
     }
}

您可以然后在动作方法创建对象。

You could then create the object in your action method.

    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();
    }

有关备查记住,在网页API默认模型联编实现不接受任何类中的操作方法的参数不具有一个无参数的构造函数。唯一的例外是当依赖注入依赖注入的加载项,如ninject或单位使用。

For future reference keep in mind that default model binder implementations in web api do not accept any class as a parameter in an action method that does not have a parameter-less constructor. The only exception to this rule is when dependency injection with dependency injection add ins such as ninject or unity are used.

这篇关于使用WebImage类在asp.net的WebAPI上传图片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-27 15:41