【ASP.NET Web API教程】5.3 发送HTML表单数据:文件上传与多部分MIME
原文:【ASP.NET Web API教程】5.3 发送HTML表单数据:文件上传与多部分MIME
注:本文是【ASP.NET Web API系列教程】的一部分,如果您是第一次看本系列教程,请先看前面的内容。
5.3 Sending HTML Form Data
5.3 发送HTML表单数据(2)
本文引自:http://www.asp.net/web-api/overview/working-with-http/sending-html-form-data,-part-2
By Mike Wasson|June 21, 2012
作者:Mike Wasson | 日期:2012-6-21
Part 2: File Upload and Multipart MIME
第2部分:文件上传与多部分MIME
This tutorial shows how to upload files to a web API. It also describes how to process multipart MIME data.
本教程演示如何对Web API上传文件。也描述如何处理多部分MIME数据。
Here is an example of an HTML form for uploading a file:
以下是一个上传文件的HTML表单(如图5-8):
<form name="form1" method="post" enctype="multipart/form-data" action="api/upload">
<div>
<label for="caption">Image Caption</label>
<input name="caption" type="text" />
</div>
<div>
<label for="image1">Image File</label>
<input name="image1" type="file" />
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
图5-8. 文件上传表单
This form contains a text input control and a file input control. When a form contains a file input control, the enctype attribute should always be "multipart/form-data", which specifies that the form will be sent as a multipart MIME message.
该表单有一个文本输入控件和一个文件输入控件。当表单含有文件输入控件时,其enctype标签属性应当总是“multipart/form-data”,它指示此表单将作为多部分MIME消息进行发送。
The format of a multipart MIME message is easiest to understand by looking at an example request:
通过考察一个示例请求,很容易理解multipart(多部分)MIME消息的格式:
POST http://localhost:50460/api/values/1 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------41184676334
Content-Length: 29278
-----------------------------41184676334
Content-Disposition: form-data; name="caption"
Summer vacation
-----------------------------41184676334
Content-Disposition: form-data; name="image1"; filename="GrandCanyon.jpg"
Content-Type: image/jpeg
(Binary data not shown)(二进制数据,未列出)
-----------------------------41184676334--
This message is divided into two parts, one for each form control. Part boundaries are indicated by the lines that start with dashes.
这条消息分成两个部件(parts),分别用于每个表单控件。部件边界由以一些破折号开始的行指示。
The part boundary includes a random component ("41184676334") to ensure that the boundary string does not accidentally appear inside a message part.
部件边界包含了一个随机组件(“41184676334”),以确保边界字符串不会偶然出现在消息部件之中。
Each message part contains one or more headers, followed by the part contents.
每一个消息部件含有一个或多个报头,后跟部件内容。
- The Content-Disposition header includes the name of the control. For files, it also contains the file name.
Content-Disposition(内容布置)报头包括控件名称。对于文件,它也包括文件名。 - The Content-Type header describes the data in the part. If this header is omitted, the default is text/plain.
Content-Type(内容类型)报头描述部件中的数据。如果该报头被忽略,默认为text/plain(文本格式)。
In the previous example, the user uploaded a file named GrandCanyon.jpg, with content type image/jpeg; and the value of the text input was "Summer Vacation".
在上一示例中,用户上传名为GrandCanyon.jpg的文件,其内容类型为image/jpeg,而文本输入框的值为“Summer Vacation”。
File Upload
文件上传
Now let's look at a Web API controller that reads files from a multipart MIME message. The controller will read the files asynchronously. Web API supports asynchronous actions using the task-based programming model. First, here is the code if you are targeting .NET Framework 4.5, which supports the async and await keywords.
现在,让我们考查从一个多部分MIME消息读取文件的控制器。该控制器将异步读取文件。Web API支持使用“基于任务的编程模型(这是关于.NET并行编程的MSDN文档 — 译者注)”的异步动作。首先,以下是针对.NET Framework 4.5的代码,它支持async和await关键字。
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
public class UploadController : ApiController
{
public async Task<HttpResponseMessage> PostFormData()
{
// Check if the request contains multipart/form-data.
// 检查该请求是否含有multipart/form-data
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
// Read the form data.
// 读取表单数据
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the file names.
// 以下描述如何获取文件名
foreach (MultipartFileData file in provider.FileData)
{
Trace.WriteLine(file.Headers.ContentDisposition.FileName);
Trace.WriteLine("Server file path: " + file.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
}
Notice that the controller action does not take any parameters. That's because we process the request body inside the action, without invoking a media-type formatter.
注意,控制器动作不取任何参数。这是因为我们是在动作中处理请求体的,不必调用media-type格式化器。
The IsMultipartContent method checks whether the request contains a multipart MIME message. If not, the controller returns HTTP status code 415 (Unsupported Media Type).
IsMultipartContent方法检查该请求是否含有多部分MIME消息。如果不是,控制器返回HTTP状态码415(不支持的媒体类型)。
The MultipartFormDataStreamProvider class is a helper object that allocates file streams for uploaded files. To read the multipart MIME message, call the ReadAsMultipartAsync method. This method extracts all of the message parts and writes them into the streams provided by the MultipartFormDataStreamProvider.
MultipartFormDataStreamProvider类是一个辅助器对象,它为上传文件分配文件流。为了读取多部分MIME消息,需调用ReadAsMultipartAsync方法。该方法提取所有消息部件,并把它们写入由MultipartFormDataStreamProvider提供的流中。
When the method completes, you can get information about the files from the FileData property, which is a collection of MultipartFileData objects.
当该方法完成时,你可以通过FileData属性获得文件的信息,该属性是一个MultipartFileData对象的集合。
- MultipartFileData.FileName is the local file name on the server, where the file was saved.
MultipartFileData.FileName是保存此文件的服务器上的一个本地文件名。 - MultipartFileData.Headers contains the part header (not the request header). You can use this to access the Content_Disposition and Content-Type headers.
MultipartFileData.Headers含有部件报头(不是请求报头)。你可以用它来访问Content_Disposition和Content-Type报头。
As the name suggests, ReadAsMultipartAsync is an asynchronous method. To perform work after the method completes, use a continuation task (.NET 4.0) or the await keyword (.NET 4.5).
正如名称所暗示的那样,ReadAsMultipartAsync是一个异步方法。为了在该方法完成之后执行一些工作,需要使用“continuation(继续)任务”(.NET 4.0)或await关键字(.NET 4.5)。
Here is the .NET Framework 4.0 version of the previous code:
以下是前述代码的.NET Framework 4.0版本:
public Task<HttpResponseMessage> PostFormData()
{
// Check if the request contains multipart/form-data.
// 检查该请求是否含有multipart/form-data
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
// Read the form data and return an async task.
// 读取表单数据,并返回一个async任务
var task = Request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
}
// This illustrates how to get the file names.
// 以下描述了如何获取文件名
foreach (MultipartFileData file in provider.FileData)
{
Trace.WriteLine(file.Headers.ContentDisposition.FileName);
Trace.WriteLine("Server file path: " + file.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
});
return task;
}
Reading Form Control Data
读取表单控件数据
The HTML form that I showed earlier had a text input control.
前面显示的HTML表单有一个文本输入控件。
<div>
<label for="caption">Image Caption</label>
<input name="caption" type="text" />
</div>
You can get the value of the control from the FormData property of the MultipartFormDataStreamProvider.
可以通过MultipartFormDataStreamProvider的FormData属性获取控件的值。
public async Task<HttpResponseMessage> PostFormData()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
await Request.Content.ReadAsMultipartAsync(provider);
// Show all the key-value pairs.
// 显示所有“键-值”对
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
Trace.WriteLine(string.Format("{0}: {1}", key, val));
}
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
FormData is a NameValueCollection that contains name/value pairs for the form controls. The collection can contain duplicate keys. Consider this form:
FormData是一个NameValueCollection(名字/值集合),它含有表单控件的“名字/值”对。该集合可能含有重复键。考虑以下表单(如图5-9):
<form name="trip_search" method="post" enctype="multipart/form-data" action="api/upload">
<div>
<input type="radio" name="trip" value="round-trip"/>
Round-Trip
</div>
<div>
<input type="radio" name="trip" value="one-way"/>
One-Way
</div>
<div>
<input type="checkbox" name="options" value="nonstop" />
Only show non-stop flights
</div>
<div>
<input type="checkbox" name="options" value="airports" />
Compare nearby airports
</div>
<div>
<input type="checkbox" name="options" value="dates" />
My travel dates are flexible
</div>
<div>
<label for="seat">Seating Preference</label>
<select name="seat">
<option value="aisle">Aisle</option>
<option value="window">Window</option>
<option value="center">Center</option>
<option value="none">No Preference</option>
</select>
</div>
</form>
图5-9. 有重复键的表单
The request body might look like this:
该请求体看上去可能像这样:
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="trip"
round-trip
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="options"
nonstop
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="options"
dates
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="seat"
window
-----------------------------7dc1d13623304d6--
In that case, the FormData collection would contain the following key/value pairs:
在这种情况下,FormData集合会含有以下“键/值”对:
- trip: round-trip
- options: nonstop
- options: dates
- seat: window
看完此文如果觉得有所收获,请给个推荐
【ASP.NET Web API教程】5.3 发送HTML表单数据:文件上传与多部分MIME的更多相关文章
- (25) java web的struts2框架的使用-基于表单的文件上传
一,首先创建一个表单页面 <body> <form action="uploads" method="post" enctype=" ...
- [原创]java WEB学习笔记49:文件上传基础,基于表单的文件上传,使用fileuoload 组件
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- 【ASP.NET Web API教程】5.2 发送HTML表单数据:URL编码的表单数据
原文:[ASP.NET Web API教程]5.2 发送HTML表单数据:URL编码的表单数据 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内 ...
- 【ASP.NET Web API教程】3.2 通过.NET客户端调用Web API(C#)
原文:[ASP.NET Web API教程]3.2 通过.NET客户端调用Web API(C#) 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的 ...
- 【ASP.NET Web API教程】2.3.7 创建首页
原文:[ASP.NET Web API教程]2.3.7 创建首页 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 7: Crea ...
- 【ASP.NET Web API教程】2.3.6 创建产品和订单控制器
原文:[ASP.NET Web API教程]2.3.6 创建产品和订单控制器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 6 ...
- 【ASP.NET Web API教程】2.3.5 用Knockout.js创建动态UI
原文:[ASP.NET Web API教程]2.3.5 用Knockout.js创建动态UI 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容 ...
- 【ASP.NET Web API教程】2.3.4 创建Admin视图
原文:[ASP.NET Web API教程]2.3.4 创建Admin视图 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 4: ...
- 【ASP.NET Web API教程】2.3.3 创建Admin控制器
原文:[ASP.NET Web API教程]2.3.3 创建Admin控制器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 3 ...
随机推荐
- 【Android LibGDX游戏引擎开发教程】第06期:图形图像的绘制(下)图片整合工具的使用
在上一篇文章中,我们提到了图片必须是2的n次方的问题.但是随着Libgdx的不断完善和发展,使用一些工具就 可以很好的解决了这样一个问题,但是它的功能又不仅仅只限于此,那么下面就来让我们看看Textu ...
- hdu 1251 统计难题 初识map
Problem Description Ignatius近期遇到一个难题,老师交给他非常多单词(仅仅有小写字母组成,不会有反复的单词出现),如今老师要他统计出以某个字符串为前缀的单词数量(单词本身也是 ...
- Poj 3246 Balanced Lineup(线段树基础)
依旧是线段树基础题 询问区间的最大值和最小值之差,只有询问,没有插入删除.继续理解基础线段树 #include <iostream> #include <algorithm> ...
- net use \\192.168.54.145 /user:administrator "12345qwert"无法连接,错误码1326
1.在远程机的"控制面板-文件夹选项-查看-简单的文件共享",去掉选取,然后再尝试连接 2.控制面板\所有控制面板项\管理工具 下-->本地安全策略-->安全设置--& ...
- python-Day4-迭代器-yield异步处理--装饰器--斐波那契--递归--二分算法--二维数组旋转90度--正则表达式
本节大纲 迭代器&生成器 装饰器 基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - ...
- 高级UIKit-09(TCPSocket发送文件、上传和下载)
[day1101_SocketSendFile]:发送文件到服务端 发送文件需要在该文件上拼接消息头,比如类型,文件名,文件大小 // 服务端 - (void)viewDidLoad { [super ...
- mac忘记登陆密码解决
重新启动苹果电脑,开机时按住“command”键+“S”键,(普通键盘按住win+s)会进入单用户模式, 出现像DOS一样的提示符 #root>依次输入如下三个命令:(注意空格 注意大小写) f ...
- JQuery学习(3)
创建精灵界面导航: 有以下图,合理的布局让图片正确显示: 先写导航栏html代码: <div id="navMenu"> <ul id="spriteN ...
- CentOS的ssh sftp配置及权限设置(流程相当完整)(关闭了SElinux才能上传了)
从技术角度来分析,几个要求: 1.从安全方面看,sftp会更安全一点 2.线上服务器提供在线服务,对用户需要控制,只能让用户在自己的home目录下活动 3.用户只能使用sftp,不能ssh到机器进行操 ...
- 基于visual Studio2013解决面试题之1409基数排序
题目