系列目录

循序渐进学.Net Core Web Api开发系列目录

本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi

一、概述

本篇介绍通过.NET core WebApi实现文件上传。

二、Controller端代码

直接上代码:

    [Route("api/files")]
[Produces("application/json")]
public class FileController : Controller
{
private readonly IHostingEnvironment _hostingEnvironment; public FileController(IHostingEnvironment hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
} [HttpPost("iform")]
public ResultObject UploadIForm(List<IFormFile> files)
{
List<String> filenames = new List<string>(); foreach (var file in files)
{
var fileName = file.FileName;
Console.WriteLine(fileName); fileName = $"/UploadFile/{fileName}";
filenames.Add(fileName); fileName = _hostingEnvironment.WebRootPath + fileName; using (FileStream fs = System.IO.File.Create(fileName))
{
file.CopyTo(fs);
fs.Flush();
}
} return new ResultObject
{
state = "Success",
resultObject = filenames
};
}

为了同时返回上传的文件名和操作状态,我们定义了一个ResultObject的类来返回信息。

    public class ResultObject
{
public String state { get; set; }
public Object resultObject { get; set; }
}

返回上传的文件名称列表的目的是因为后台可能会给文件重新命名,以避免冲突,新的文件名称需要让前台知道。

后台的files是通过传入的参数获得的,还有其他两种方法可以获取到文件,效果一样:

       [HttpPost]
public ResultObject UploadAjax()
{
var files = Request.Form.Files;
...
}

或:

       public ResultObject UploadForm(IFormCollection form)
{
var files = form.Files;
...
}

除了获取到files的方式不同,其他操作完全一致。

三、前端代码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="lib/jquery/dist/jquery.min.js"></script>
<script src="lib/jquery-form/dist/jquery.form.min.js"></script>
<script type="text/javascript">
function AjaxFormDataUploadfile() {
var fileUpload = $("#files").get();
var files = fileUpload.files;
var data = new FormData();
for (var i = ; i < files.length; i++) {
data.append("files", files[i]);
} $.ajax({
type: "POST",
url: "/api/files/iform",
contentType: false,
processData: false,
data: data,
success: function (message) {
alert("success");
},
error: function () {
alert("上传文件出现错误!");
}
});
} </script>
</head>
<body>
<form id="myform" method="post" action="/api/files/iform" enctype="multipart/form-data">
<input type="file" id="files" name="files" multiple /> <br /><br />
<input id="formupload" type="button" value="Form Data Upload" onclick="AjaxFormDataUploadfile();" /><br /><br />
</form>
</body>
</html>

两个注意点:

1、form要提供enctype="multipart/form-data" 属性

2、如果要上传多个文件,文件表单需要提供multiple属性

这里我们通过FormData对象的append操作来构建提交的数据,根据我上一篇博客提到的,这里提交数据还有其他两个办法:

        function formuploadfile() {
$("#myform").ajaxSubmit();
}

或者:

        function Ajaxuploadfile() {
var formdata = new FormData(document.getElementById("myform")); $.ajax({
type: "POST",
url: "/api/files/iform",
contentType: false,
processData: false,
data: formdata,
success: function (result) {
alert("success");
$.each(result.resultObject, function (i, filename) {
alert(filename);
});
},
error: function () {
alert("上传文件出现错误!");
}
});
}

具体选择哪种方式,要看前端的需求,个人认为 var formdata = new FormData(document.getElementById("myform")); 比较方便。

四、上传大文件

上传大文件和上传小文件代码是一样的,关键是上传大文件时间太长,需要前端提供进度报告,不然用户体验太差。

解决的方案是利用ajax的HXR对象。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="lib/jquery/dist/jquery.min.js"></script>
<script src="lib/jquery-form/dist/jquery.form.min.js"></script>
<script type="text/javascript"> function AjaxuploadfileWithprogress() {
var formdata = new FormData(document.getElementById("myform")); $.ajax({
type: "POST",
url: "/api/files/iform",
contentType: false,
processData: false,
data: formdata,
success: function (result) {
alert("success");
$.each(result.resultObject, function (i, filename) {
alert(filename);
});
},
error: function () {
alert("上传文件出现错误!");
},
xhr: function () {
var xhr = $.ajaxSettings.xhr();
if (onprogress && xhr.upload) {
xhr.upload.addEventListener("progress", onprogress, false);
return xhr;
}
}
});
} function onprogress(evt)
{
var loaded = evt.loaded; //已经上传大小
var tot = evt.total; //附件总大小
var per = Math.floor( * loaded / tot); //百分比
$("#son").html(per + "%");
$("#son").css("width", per + "%");
}
</script>
<style type="text/css">
#parent {
width: 550px;
height: 10px;
border: 2px solid #09F;
}
#son {
width: ;
height: %;
background-color: #09F;
text-align: center;
line-height: 10px;
font-size: 20px;
font-weight: bold;
}
</style>
</head>
<body>
<form id="myform" method="post" action="/api/files/iform" enctype="multipart/form-data">
<div>
<div>
<br />
<p>表单多个上传文件:</p><br />
<input type="file" id="files" name="files" multiple /> <br /><br />
<input id="formuploadprogress" type="button" value="Ajax Upload Progress" onclick="AjaxuploadfileWithprogress();" /><br /><br />
<div id="parent">
<div id="son"></div>
</div>
</div>
</div>
</form>
</body>
</html>

此时,可以看到上传进度条了,可以选择一个大文件测试一下。或者把浏览器的传输速度调低也可以进行调试。

五、为Swagger提供文件上传调试功能支持

目前swagger是不支持List<IFormFile>类型的,为了方便调试,我们为swagger提供该类型的支撑。

新增类:

public class SwaggerFileUploadListFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (!context.ApiDescription.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) &&
!context.ApiDescription.HttpMethod.Equals("PUT", StringComparison.OrdinalIgnoreCase))
{
return;
} var fileParameters = context.ApiDescription.ActionDescriptor.Parameters.Where(n => n.ParameterType == typeof(List<IFormFile>)).ToList(); if (fileParameters.Count < )
{
return;
} operation.Consumes.Add("multipart/form-data");
foreach (var fileParameter in fileParameters)
{
var parameter = operation.Parameters.Single(n => n.Name == fileParameter.Name);
operation.Parameters.Remove(parameter); NonBodyParameter p = new NonBodyParameter
{
Name = parameter.Name,
In = "formData",
Description = parameter.Description,
Required = parameter.Required,
Type = "file"
}; operation.Parameters.Add(p);
}
}
}

在Startup类的ConfigureServices方法里注册该过滤器:

       public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddCors(); services.AddSwaggerGen(option =>
{
option.SwaggerDoc("v1", new Info
{
Version = "v1",
Title = "SaleService接口文档",
Description = "RESTful API for SaleService.",
TermsOfService = "None",
Contact = new Contact { Name = "seabluescn", Email = "seabluescn@163.com", Url = "" }
});

option.OperationFilter<SwaggerFileUploadListFilter>();
//Set the comments path for the swagger json and ui.
var basePath = PlatformServices.Default.Application.ApplicationBasePath;
var xmlPath = Path.Combine(basePath, "SaleService.xml");
option.IncludeXmlComments(xmlPath);
});
}

此时可以通过swagger选择文件了

但有个缺点是只能上传一个文件,如何实现可以选择多个文件还不会搞。

循序渐进学.Net Core Web Api开发系列【5】:文件上传的更多相关文章

  1. 循序渐进学.Net Core Web Api开发系列【0】:序言与目录

    一.序言 我大约在2003年时候开始接触到.NET,最初在.NET framework 1.1版本下写过代码,曾经做过WinForm和ASP.NET开发.大约在2010年的时候转型JAVA环境,这么多 ...

  2. 循序渐进学.Net Core Web Api开发系列【16】:应用安全续-加密与解密

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 应用安全除 ...

  3. 循序渐进学.Net Core Web Api开发系列【15】:应用安全

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇介绍W ...

  4. 循序渐进学.Net Core Web Api开发系列【14】:异常处理

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇介绍异 ...

  5. 循序渐进学.Net Core Web Api开发系列【13】:中间件(Middleware)

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇介绍如 ...

  6. 循序渐进学.Net Core Web Api开发系列【12】:缓存

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇介绍如 ...

  7. 循序渐进学.Net Core Web Api开发系列【11】:依赖注入

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇介绍如 ...

  8. 循序渐进学.Net Core Web Api开发系列【10】:使用日志

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.本篇概述 本篇介 ...

  9. 循序渐进学.Net Core Web Api开发系列【9】:常用的数据库操作

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇描述一 ...

  10. 循序渐进学.Net Core Web Api开发系列【8】:访问数据库(基本功能)

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇讨论如 ...

随机推荐

  1. phpstorm 配置 webpack @ 别名跳转

    webstorm中专门有webpack的相关配置,默认的路径直接是项目根目录下的 webpack.config.js,但是我们用各种cli生成的项目中,webpack的配置一般都是在build下,导致 ...

  2. Json对象和Json字符串的区别

    说白了,字符串都是带引号的. 尤其是在使用springmvc的时候,后台@RequestBody接受的是一个json格式的字符串,一定是一个字符串.  参考这个博客还可以: https://blog. ...

  3. JAVA io 包小结

    IO 无非读写 I --> Reader  O--> Writer 为了方便字符 或者 文本文件的 操作创造出了 字符流 尤其是 缓冲字符输入输出流(BufferedReader,Buff ...

  4. 作业:JavaScript(数组篇-poker)给我的徒弟出个题。。。记得早点写完,然后大家3人可以早点打牌了

    吐槽一下:“今天实际上我左思右想,写个什么东西好呢!手上的笔转了半天....最后还是给自己留点余地!看着他们什么酒店管理系统,呼叫中心系统之类的....简直是把自己固定死了!感觉一撸到底的感觉!!!我 ...

  5. [机器学习&数据挖掘]朴素贝叶斯数学原理

    1.准备: (1)先验概率:根据以往经验和分析得到的概率,也就是通常的概率,在全概率公式中表现是“由因求果”的果 (2)后验概率:指在得到“结果”的信息后重新修正的概率,通常为条件概率(但条件概率不全 ...

  6. PHP删除数组中空值

    array_filter   函数的功能是利用回调函数来对数组进行过滤,一直都以为用回调函数才能处理, 却没有发现手册下面还有一句,如果没有回调函数,那么默认就是删除数组中值为false的项目 代码: ...

  7. perl6 中将 字符串 转成十六进制

    say Blob.new('abcde'.encode('utf8')).unpack("H*"); say '0x'~'abcde'.encode('utf8').unpack( ...

  8. XSS小游戏通关Writeup

    源码下载:https://files.cnblogs.com/files/nul1/xss%E7%BB%83%E4%B9%A0%E5%B0%8F%E6%B8%B8%E6%88%8F.zip 我也没啥可 ...

  9. Linux驱动技术(四) _异步通知技术【转】

    转自:https://www.cnblogs.com/xiaojiang1025/p/6376561.html 异步通知的全称是"信号驱动的异步IO",通过"信号&quo ...

  10. nginx:支持跨域访问

    在http节点中配置: #支持跨域访问 add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Header ...