前言

最近因维护.NET和.NET Core项目用到文件上传功能,虽说也做过,但是没做过什么对比,借此将二者利用Ajax通过FormData上传文件做一个总结,通过视图提交表单太简单,这里不做阐述,希望对有需要的童鞋能有力所能及的帮助。

.NET Web APi FormData文件上传

我们将参数和文件都通过FormData来上传,给出如下HTML代码

<div class="form-horizontal" style="margin-top:80px;">
<div class="form-group">
<label class="control-label col-md-2" for="caption">标题</label>
<div class="col-md-10">
<input name="title" id="title" type="text" />
</div>
</div> <div class="form-group">
<label class="control-label col-md-2" for="caption">文件</label>
<div class="col-md-10">
<input name="file" id="file" multiple type="file" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" id="btn" value="提交" class="btn btn-success" />
</div>
</div>
</div>

恕我有点强迫症,界面好看点,看着也舒服,接下来则是脚本自然不用多说,利用FormData上传文件网上一搜遍地都是

$(function () {
$('#btn').click(function () { var data = new FormData(); var title = $('#title').val();
data.append("title", title); var files = $('#file')[0].files;;
for (var i = 0; i < files.length; i++) {
data.append("file", files[i]);
}
$.ajax({
url: '/api/upload/upload',
type: "post",
cache: false,
contentType: false,
processData: false,
data: data,
});
});
});

不过需要注意的是,对现代大多浏览器都都已支持将上述contentType设置为false后,就是在请求头中添加multipart/form-data,若是老版本浏览器则需要在请求头中手动添加表单多文件上传标识,如下

beforeSend: function (request) {
request.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + data.boundary);
}

前端我们已经搞完,接下来我们回到后台,.NET Web APi已提供专门读取FormData数据的APi,如下:

//检查请求是否包含multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
} //将文件存储到App_Data文件夹下
var root = HttpContext.Current.Server.MapPath("~/App_Data"); //实例化MultipartFormDat流
var provider = new MultipartFormDataStreamProvider(root); // 读取表单数据
await Request.Content.ReadAsMultipartAsync(provider);

若上传2个文件,此时上传App_Data目录下的文件,如下这般

若要读取提交的表单参数,我们如下获取

//获取表单参数数据
var formData = provider.FormData;

那么我们怎么将上述类似临时文件数据转换为我们上传的文件数据呢?我们只需将上述文件名转换我们上传的文件名或者其他自定义文件名称即可,如下:

// 获取文件数据
foreach (MultipartFileData file in provider.FileData)
{
string fileName = file.Headers.ContentDisposition.FileName; if (fileName.StartsWith("\"") && fileName.EndsWith("\""))
{
fileName = fileName.Trim('"');
}
if (fileName.Contains(@"/") || fileName.Contains(@"\"))
{
fileName = Path.GetFileName(fileName);
} //将本地文件转换为实际所需文件
File.Move(file.LocalFileName, Path.Combine(root, fileName));
}

完美解决问题,当然除了通过上述流读取表单相关数据外,.NET Web APi还提供了内存表单流,只是利用此流时,表单参数和文件放置在一起,我们需要通过文件相关参数来做区分,然后分别获取文件和表单参数,如下:

var provider = new MultipartMemoryStreamProvider();

await Request.Content.ReadAsMultipartAsync(provider);

var formData = new NameValueCollection();

foreach (var httpContent in provider.Contents)
{
var formFileName = httpContent.Headers.ContentDisposition?.FileName?.Trim('\"');
var formContentType = httpContent.Headers?.ContentType?.ToString(); if (!string.IsNullOrEmpty(formFileName) && !string.IsNullOrEmpty(formContentType))
{
//文件数据
using (var fileStream = new FileStream(root, FileMode.Create))
{
await httpContent.CopyToAsync(fileStream);
}
}
else
{
//表单参数
var formFieldName = httpContent.Headers.ContentDisposition.Name; var formFieldValue = await httpContent.ReadAsStringAsync(); formData.Add(formFieldName, formFieldValue);
}
}

.NET Core Web APi FormData文件上传

HTML和脚本在上述已经提供,这里我们只需关注APi获取即可。在.NET Core中没有专门提供获取FormData数据的APi,那么我们是如何获取的呢?网上找了一大圈大部分是来自广告网站CSDN,不过这些文章都是转载的博客园,都是如下这样获取

[Route("api/[controller]/[action]")]
[ApiController]
public class UploadController : ControllerBase
{
public IActionResult Upload()
{
var files = Request.Form.Files; return Ok();
}
}

如上也没问题,我能说你这思路还停留在.NET Web APi吗,啥年代了,还通过请求上下文去获取,.NET Core灵活绑定机制使用起来它不香吗,通过如下直接绑定岂不完事

此时有的童鞋又有疑问了,上传不仅仅包括文件还包括参数,比如上述还有标题,那该如何是好,啊,这个问题,.NET Core的强类型绑定机制它不香吗,如下定义强类型:

public class ExampleUpload
{
public string Title { get; set; }
public List<IFormFile> Files { get; set; }
}

注意:绑定参数时一定要使用[FromForm],否则将出现请求415,同时也要将前端Ajax FormData文件的参数名和强类型参数名一致。

[Route("api/[controller]/[action]")]
[ApiController]
public class UploadController : ControllerBase
{
public IActionResult Upload([FromForm]ExampleUpload example)
{
return Ok();
}
}

总结

.NET Core用起来就是这么流畅和舒适,它也是真的香啊,好了,关于此二者多文件上传暂且总结于此,我们下节再会。

.NET和.NET Core Web APi FormData多文件上传对比的更多相关文章

  1. ASP.NET Core WEB API 使用element-ui文件上传组件el-upload执行手动文件文件,并在文件上传后清空文件

    前言: 从开始学习Vue到使用element-ui-admin已经有将近快两年的时间了,在之前的开发中使用element-ui上传组件el-upload都是直接使用文件选取后立即选择上传,今天刚好做了 ...

  2. ASP.NET 异步Web API + jQuery Ajax 文件上传代码小析

    该示例中实际上应用了 jquery ajax(web client) + async web api 双异步. jquery ajax post $.ajax({ type: "POST&q ...

  3. .net core 基于multipart/form-data的文件上传,这里以图片上传为例

    首先传递的数据格式大概如下: 然后就可以在后端获取数据了:直接上代码了哈: [HttpPost]        ///分别获取 data数据和调用图片上传方法 public async Task< ...

  4. Multipart/form-data POST文件上传详解

    Multipart/form-data POST文件上传详解 理论 简单的HTTP POST 大家通过HTTP向服务器发送POST请求提交数据,都是通过form表单提交的,代码如下: <form ...

  5. Multipart/form-data POST文件上传详解(转)

    Multipart/form-data POST文件上传详解 理论 简单的HTTP POST 大家通过HTTP向服务器发送POST请求提交数据,都是通过form表单提交的,代码如下: <form ...

  6. 构建multipart/form-data实现文件上传

    构建multipart/form-data实现文件上传 通常文件上传都是通过form表单中的file控件,并将form中的content-type设置为multipart/form-data.现在我们 ...

  7. 百度Web Uploader组件实现文件上传(一)

    Web Uploader WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件.在现代的浏览器里面能充分发挥HTML5的优势 ...

  8. SpringBoot | 第十七章:web应用开发之文件上传

    前言 上一章节,我们讲解了利用模版引擎实现前端页面渲染,从而实现动态网页的功能,同时也提出了兼容jsp项目的解决方案.既然开始讲解web开发了,我们就接着继续往web这个方向继续吧.通常,我们在做we ...

  9. SpringBoot --web 应用开发之文件上传

    原文出处: oKong 前言 上一章节,我们讲解了利用模版引擎实现前端页面渲染,从而实现动态网页的功能,同时也提出了兼容jsp项目的解决方案.既然开始讲解web开发了,我们就接着继续往web这个方向继 ...

随机推荐

  1. OSCP Learning Notes - Enumeration(3)

    SMB Enumeration 1. Set the smb configurations. locate smb.conf vim /etc/samba/smb.conf Insert the gl ...

  2. Web Scraping using Python Scrapy_BS4 - using BeautifulSoup and Python

    Use BeautifulSoup and Python to scrap a website Lib: urllib Parsing HTML Data Web scraping script fr ...

  3. javascript : 复杂数据结构拷贝实验

    数组深拷贝看起来很简单. array.concat()就行了. 但是,如果数组里有对象呢? 实际上,你以为你拷贝了对象,但实际上你只拷贝了对象的引用(指针)! 我们可以做个试验. // test le ...

  4. 哈夫曼编码+python实现

    关于哈夫曼树怎么构建的.哈夫曼编码怎么求,请参考 哈夫曼树及python实现 这些基础的东西就不在这里阐述了,本文直接上代码. 参考链接:哈夫曼树的 Python 实现 哈夫曼树的构建和编码 ''' ...

  5. 04 CMD规范基础使用详解

    CMD模块规范 1.1 CMD规范说明 专门用于浏览器端,并且模块的加载是异步的,而且只有模块使用时才会加载执行: CMD规范的语法类似于Commonjs + AMD --定义模块使用AMD语法,暴露 ...

  6. APP自动化 -- 滑动解锁、滑动验证

    一.解锁 1.代码 2.效果 1)执行效果 2)点位效果

  7. 宽度优先搜索--------迷宫的最短路径问题(dfs)

    宽度优先搜索运用了队列(queue)在unility头文件中 源代码 #include<iostream>#include<cstdio>#include<queue&g ...

  8. vue学习(四) v-on:事件绑定

    //html <div id="app"> <input type="button" value="ok" v-bind: ...

  9. Laravel 使用阿里云 oss 存储对象

    一.下载安装 composer require jacobcyl/ali-oss-storage 二.注册服务提供者 在config/app.php的providers下添加: //阿里云OSS对象存 ...

  10. django表单使用

    一.表单常用字段类型及参数 表单可以自动生成html代码,每一个字段默认有一个html显示样式,大多数默认为输入框. 字段相当于正则表达式的集合,能够对表单传入的数据进行校验,并且某一部分校验失败时会 ...