前言

最近因维护.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. 机器学习实战基础(二十):sklearn中的降维算法PCA和SVD(一) 之 概述

    概述 1 从什么叫“维度”说开来 我们不断提到一些语言,比如说:随机森林是通过随机抽取特征来建树,以避免高维计算:再比如说,sklearn中导入特征矩阵,必须是至少二维:上周我们讲解特征工程,还特地提 ...

  2. 深入浅出AQS源码解析

    最近一直在研究AQS的源码,希望可以更深刻的理解AQS的实现原理.虽然网上有很多关于AQS的源码分析,但是看完以后感觉还是一知半解.于是,我将自己的整个理解过程记录下来了,希望对大家有所帮助. 基本原 ...

  3. mysql groupby 字段合并问题(group_concat)

    在我们的日常mysql查询中,我们可能会遇到这样的情况: 对表中的所有记录进行分类,并且我需要得到每个分类中某个字段的全部成员. 上面的话,大家看起来可能不太好懂,下面举一个例子来给大家说明. 现在我 ...

  4. QQ音乐Android客户端Web页面通用性能优化实践

    QQ音乐 Android 客户端的 Web 页面日均 PV 达到千万量级,然而页面的打开耗时与 Native 页面相距甚远,需要系统性优化.本文将介绍 QQ 音乐 Android 客户端在进行 Web ...

  5. ASP.Net Core 3.1 With Autofac ConfigureServices returning an System.IServiceProvider isn't supported.

    ASP.Net Core 3.1 With Autofac ConfigureServices returning an System.IServiceProvider isn't supported ...

  6. 牛客练习赛66A题解

    思路 令 \(sq=\sqrt x\) ,则答案必然在 $ sq^2$ 和 $ (sq+1)^2 $ 之间,两者比较一下谁离 \(x\) 最近,就是答案了. 代码 #include <bits/ ...

  7. C++语法小记---string类

    string类 #include <iostream> #include <string> using namespace std; // 实现字符串右移, 例子hello & ...

  8. java 手机号码归属地查询

    下面是利用第三方接口实现手机号码归属地查询 (复制请标明出处或留言) package com.test.yyc; import java.io.BufferedReader; import java. ...

  9. boot camp要求独立的fat分区

    先在windows把u盘用diskpart clean掉分区表 然后在苹果里面,给u盘重新分区,分区表不要选择GUID,选择主引导记录,格式选择fat,OK

  10. centos7 安装 isign

    centos应该自带python和openssl,这两个就不用装了, 先安装zip和git yum install -y unzip zip yum install git 然后克隆代码: https ...