• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ASP.NETMVCWebAPI从入门到精通(二)–客户端和WebService之间文件传输 ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

要解决这些问题,要了解一下WebAPI的基本工作方式。

(一)WebAPI中工作的Class

在MVC中大家都知道,获取Request和Response使用HttpRequest和HttpResponse两个类,在WebAPI中使用两外两个类:
HttpRequestMessage和HttpResponseMessage,分别用于封装Requset和Response。除了这两个类之外,还有一个常见的抽象 类:HttpMessageHandler,用于过滤和加工HttpRequestMessage和HttpResponseMessage

(二)解决第一个问题

其 实第一个问题之所以被提出来应该是和客户端有关,如果客户端的请求是我们手写提交的,比如使用HttpClient封装的请求,则要传递文件之前,我们一 般会进行一次序列化,转化为二进制数组之类的,在网络上传输。这样的话,在Controller中的Action参数里,我们只需要接收这个二进制数组类 型的对象就可以了。
但是如果客户端是Web Form呢,比如我们提交一个Form到指定的Controller的Action中,这个Action要接收什么类型的参数呢?
或者我们问另外一个问题,如果我将Web Form提交到一个WebAPI的Action中 ,我要怎么去取出这个表单中的数据呢?
其 实我们应该想到:我们的Action设置的参数之所以能够被赋值,是因为WebAPI的架构中在调用Action时将HTTP请求中的数据解析出来分别赋 值给Action中的参数,如果真是这样的话,我们只需要在Action中获取到HTTP请求,然后直接获取请求里面的数据,就能解决上面的问题。
这 种想法是正确的,只不过,此时的HTTP请求已经不是最原始的HTTP Request,而是已经被转化成了HttpRequestMessage,在Action中,我们可以直接调用base.Requet来得到这个HttpRequestMessage实例,通过这个实例我们就可以随心所欲的取出HTTP请求中想要的数据。

2.1从RequestMessage中获取普通表单数据

这里的普通表单是指不包含File的表单,也就是说表单的enctype值不是multipart/form-data,这时,表单的数据默认情况下是以Json来传递的
如下页面

 

<form name="form" action="~/api/FormSubmit?key=11234" method="post">

<input type="text" name="key" />

<br />

<input type="text" name="value" />

<br />

<input type="submit" />

</form>

 

捕获到的请求为

提交到对应的Action为:

 

        [HttpPost]

public async void submitForm()

        {

            StringBuilder sb = new StringBuilder();

            HttpContent content = Request.Content;

            JsonObject jsonValue = await content.ReadAsOrDefaultAsync<JsonObject>();

foreach (var x in jsonValue)

            {

                sb.Append(x.Key);

string va ;

if (x.Value.TryReadAs<string>(out va))

                {

                    sb.Append(va);

                }

            }

        }

 

这样最后可以得到 Json的值:{"key":"123","value":"123"} sb处理后的值为:key123value123

注:在该action中使用到了关键字async和await,这些在4.5中新提出的关键字主要是用于进行多线程取值的,在MVCAPI的设计中,大部分的方法都被设计成类似于下面的方法

public static Task<T> ReadAsOrDefaultAsync<T>(this HttpContent content);

返 回值是一个Task,这种返回新线程的方法虽然可以提高系统的响应能力,但是多线程取值会给编码带来不便,所以新出的关键字await用于阻塞当前线程并 获取目标线程的返回值,在方法体中使用await关键字后要求将方法声明为async用来表示该方法是异步的,并且返回值必须为void或者将返回者封装 在一个Task中
当然,如果你不喜欢这种写法,上面的action也可以写为:

            Task readTask = content.ReadAsOrDefaultAsync<JsonObject>().ContinueWith((task) => { jsonValue = task.Result; });

            readTask.Wait();

2.2从RequestMessage中获取multipart表单数据
将view页面改写为

 

<form name="form" action="~/api/FormSubmit?key=11234" method="post" enctype="multipart/form-data" >

<input type="text" name="key" />

<br />

<input type="text" name="value" />

<br />

<input type="file" name="file" />

<br />

<input type="submit" />

</form>

 

此时捕获到得请求是


这里的文件内容被捕获软件解析成字符串,当然如果我上传的是其他的非文本格式的文件,文件会被转化为二进制数组
这时如果我们不更改action,而直接调用,会发生错误,原因很明显,这个HTTP的报文内容是无法被转换为JSON的,这时我们需要将表单的报文解析成另外一种格式

 

                IEnumerable<HttpContent> bodyparts = await content.ReadAsMultipartAsync();

foreach (var bodypart in bodyparts)

                {

string name;

                    name = bodypart.Headers.ContentDisposition.Name;

                    sb.Append(name + ":");

if (bodypart.Headers.Contains("filename"))

                    {

                        Stream stream = await bodypart.ReadAsStreamAsync();

                        StreamReader reader = new StreamReader(stream);

                        sb.Append(reader.ReadToEnd());

                        sb.Append("----");

                    }

else

                    {

string val = await bodypart.ReadAsStringAsync();

                        sb.Append(val);

                        sb.Append("----");

                    }

                }

 

得到的处理后的sb值为:

{"key":123----"value":123----"file":******{文件的内容}*****----}
整合后的Action为

 

        [HttpPost]

public async void submitForm()

        {

            StringBuilder sb = new StringBuilder();

            HttpContent content = Request.Content;

if (content.IsMimeMultipartContent())

            {

                IEnumerable<HttpContent> bodyparts = await content.ReadAsMultipartAsync();

foreach (var bodypart in bodyparts)

                {

string name;

                    name = bodypart.Headers.ContentDisposition.Name;

                    sb.Append(name + ":");

if (bodypart.Headers.Contains("filename"))

                    {

                        Stream stream = await bodypart.ReadAsStreamAsync();

                        StreamReader reader = new StreamReader(stream);

                        sb.Append(reader.ReadToEnd());

                        sb.Append("----");

                    }

else

                    {

string val = await bodypart.ReadAsStringAsync();

                        sb.Append(val);

                        sb.Append("----");

                    }

                }

            }

else

            {

                JsonObject jsonValue = await content.ReadAsOrDefaultAsync<JsonObject>();

foreach (var x in jsonValue)

                {

                    sb.Append(x.Key);

string va;

if (x.Value.TryReadAs<string>(out va))

                    {

                        sb.Append(va);

                    }

                }

            }

        }


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
ASP.NETEval四种绑定方式发布时间:2022-07-10
下一篇:
Asp.netcore学习笔记(Azurekey-vault)发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap