This chapter shares with you an example of uploading files using .NetCore's MVC framework. The main contents include: form submission for upload, ajax upload, ajax submission + upload progress effect, Task parallel processing + ajax submission + upload progress, It is very helpful to everyone. If you are interested, please follow the editor to learn
This chapter shares with you an example of uploading files using the MVC framework of .NetCore. The main contents are: form submission and upload, ajax Upload, ajax submission + upload progress effect, Task parallel processing + ajax submission + upload progress. I believe you will get a good harvest after reading the content of the article. If you can, you might as well give it a like; because the computer ran out of power yesterday, I will almost finish writing it. The content was not saved, so I came to the company early this morning and started over from scratch. The power outage was indeed a headache, but for the sake of the community’s sharing environment, it was worth it. Without further ado, let’s get into today’s main part;
Upload a set of pictures in form
Let’s take a look at our html code first. Here is a brief explanation of what is required to upload files. Set the enctype="multipart/form-data" attribute and post method in the form element. If you want to upload multiple files, you need to set the file type='file' element to her attribute multiple='multiple', so With the following content:
<form class="form-horizontal" action="/Home/FileUp" method="post" enctype="multipart/form-data"> <input type="file" name="MyPhoto" class="form-control" multiple /> <br /> <button class="btn btn-default">form上传</button> <br /> <span style="color:red">@ViewData["MsgBox"]</span> </form>
Due to the use of form submission, this test case only uses the default type=submit of the button element to submit the form, and the corresponding code in the background Action As follows:
/// <summary> /// form提交上传 /// </summary> /// <param name="user"></param> /// <returns></returns> [HttpPost] public async Task<IActionResult> FileUp(MoUser user) { if (user.MyPhoto == null || user.MyPhoto.Count <= 0) { MsgBox("请上传图片。"); return View(); } //var file = Request.Form.Files; foreach (var file in user.MyPhoto) { var fileName = file.FileName; var contentType = file.ContentType; var len = file.Length; var fileType = new string[] { "image/jpeg", "image/png" }; if (!fileType.Any(b => b.Contains(contentType))) { MsgBox($"只能上传{string.Join(",", fileType)}格式的图片。"); return View(); } if (len > 1024 * 1024 * 4) { MsgBox("上传图片大小只能在4M以下。"); return View(); } var path = Path.Combine(@"D:\F\学习\vs2017\netcore\netcore01\WebApp01\wwwroot\myfile", fileName); using (var stream = System.IO.File.Create(path)) { await file.CopyToAsync(stream); } } MsgBox($"上传成功"); return View(); }
The Action from the front end to the back end has to be said that this form submission method is quite simple. It should be noted that the entity model method used in the Action here is Corresponding to the uploaded file information, the MoUser class is customized here, and the name of the file type='file' in the html form is matched through the attribute
public List ##Attribute name
name="MyPhoto":
public class MoUser { public int UserId { get; set; } = 1; public string UserName { get; set; } = "神牛步行3"; public List<IFormFile> MyPhoto { get; set; } }
ajax uploads a set of pictures
Here you need to modify some things in the html in the above example. Instead of using form submission, a normal button button is specified to trigger ajax submission. The complete html code is as follows:<form class="form-horizontal" id="form01" method="post" enctype="multipart/form-data"> <input type="file" name="MyPhoto01" class="form-control" multiple /> <br /> <button type="button" id="btnAjax" class="btn btn-default">ajax上传</button> <br /> <span style="color:red" id="span01"></span> </form>
##
$("#btnAjax").on("click", function () { var msg = $("#span01"); var form = document.getElementById("form01"); //console.log(form); var data = new FormData(form); $.ajax({ type: "POST", url: "/home/AjaxFileUp", data: data, contentType: false, processData: false, success: function (data) { if (data) { msg.html(data.msg); } }, error: function () { msg.html("上传文件异常,请稍后重试!"); } }); });
/// <summary> /// ajax无上传进度效果上传 /// </summary> /// <returns></returns> [HttpPost] public async Task<JsonResult> AjaxFileUp() { var data = new MoData { Msg = "上传失败" }; try { var files = Request.Form.Files.Where(b => b.Name == "MyPhoto01"); //非空限制 if (files == null || files.Count() <= 0) { data.Msg = "请选择上传的文件。"; return Json(data); } //格式限制 var allowType = new string[] { "image/jpeg", "image/png" }; if (files.Any(b => !allowType.Contains(b.ContentType))) { data.Msg = $"只能上传{string.Join(",", allowType)}格式的文件。"; return Json(data); } //大小限制 if (files.Sum(b => b.Length) >= 1024 * 1024 * 4) { data.Msg = "上传文件的总大小只能在4M以下。"; return Json(data); } //写入服务器磁盘 foreach (var file in files) { var fileName = file.FileName; var path = Path.Combine(@"D:\F\学习\vs2017\netcore\netcore01\WebApp01\wwwroot\myfile", fileName); using (var stream = System.IO.File.Create(path)) { await file.CopyToAsync(stream); } } data.Msg = "上传成功"; data.Status = 2; } catch (Exception ex) { data.Msg = ex.Message; } return Json(data); }
ajax submission + upload progress + a set of image uploadsSimilarly, let’s look at the corresponding html code first. In fact, it is almost the same as example 2, except that the name has been changed:
<form class="form-horizontal" id="form02" method="post" enctype="multipart/form-data"> <input type="file" name="MyPhoto02" class="form-control" multiple /> <br /> <button type="button" id="btnAjax02" class="btn btn-default">ajax上传进度效果上传</button> <br /> <span style="color:red" id="span02"></span> </form>
$("#btnAjax02").on("click", function () { var interBar; var msg = $("#span02"); msg.html("上传中,请稍后..."); var form = document.getElementById("form02"); //console.log(form); var data = new FormData(form); $.ajax({ type: "POST", url: "/home/AjaxFileUp02", data: data, contentType: false, processData: false, success: function (data) { if (data) { msg.html(data.msg); //清除进度查询 if (interBar) { clearInterval(interBar); } } }, error: function () { msg.html("上传文件异常,请稍后重试!"); if (interBar) { clearInterval(interBar); } } }); //获取进度 interBar = setInterval(function () { $.post("/home/ProgresBar02", function (data) { if (data) { var isClearVal = true; var strArr = []; $.each(data, function (i, item) { strArr.push('文件:' + item.fileName + ",当前上传:" + item.percentBar + '<br/>'); if (item.status != 2) { isClearVal = false; } }); msg.html(strArr.join('')); if (isClearVal) { if (interBar) { clearInterval(interBar); } } } }); }, 200); });
public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddMvc(); //添加cache支持 services.AddDistributedMemoryCache(); }
readonly IMemoryCache _cache; public HomeController(IOptions<MoOptions> options, ILogger<HomeController> logger, IMemoryCache cache) { this._options = options.Value; _logger = logger; _cache = cache; }
private string cacheKey = "UserId_UpFile"; private string cacheKey03 = "UserId_UpFile03"; /// <summary> /// ajax上传进度效果上传 /// </summary> /// <returns></returns> [HttpPost] public async Task<JsonResult> AjaxFileUp02() { var data = new MoData { Msg = "上传失败" }; try { var files = Request.Form.Files.Where(b => b.Name == "MyPhoto02"); //非空限制 if (files == null || files.Count() <= 0) { data.Msg = "请选择上传的文件。"; return Json(data); } //格式限制 var allowType = new string[] { "image/jpeg", "image/png" }; if (files.Any(b => !allowType.Contains(b.ContentType))) { data.Msg = $"只能上传{string.Join(",", allowType)}格式的文件。"; return Json(data); } //大小限制 if (files.Sum(b => b.Length) >= 1024 * 1024 * 4) { data.Msg = "上传文件的总大小只能在4M以下。"; return Json(data); } //初始化上传多个文件的Bar,存储到缓存中,方便获取上传进度 var listBar = new List<MoBar>(); files.ToList().ForEach(b => { listBar.Add(new MoBar { FileName = b.FileName, Status = 1, CurrBar = 0, TotalBar = b.Length }); }); _cache.Set<List<MoBar>>(cacheKey, listBar); //写入服务器磁盘 foreach (var file in files) { //总大小 var totalSize = file.Length; //初始化每次读取大小 var readSize = 1024L; var bt = new byte[totalSize > readSize ? readSize : totalSize]; //当前已经读取的大小 var currentSize = 0L; var fileName = file.FileName; var path = Path.Combine(@"D:\F\学习\vs2017\netcore\netcore01\WebApp01\wwwroot\myfile", fileName); using (var stream = System.IO.File.Create(path)) { //await file.CopyToAsync(stream); //进度条处理流程 using (var inputStream = file.OpenReadStream()) { //读取上传文件流 while (await inputStream.ReadAsync(bt, 0, bt.Length) > 0) { //当前读取的长度 currentSize += bt.Length; //写入上传流到服务器文件中 await stream.WriteAsync(bt, 0, bt.Length); //获取每次读取的大小 readSize = currentSize + readSize <= totalSize ? readSize : totalSize - currentSize; //重新设置 bt = new byte[readSize]; //设置当前上传的文件进度,并重新缓存到进度缓存中 var bars = _cache.Get<List<MoBar>>(cacheKey); var currBar = bars.Where(b => b.FileName == fileName).SingleOrDefault(); currBar.CurrBar = currentSize; currBar.Status = currentSize >= totalSize ? 2 : 1; _cache.Set<List<MoBar>>(cacheKey, bars); System.Threading.Thread.Sleep(1000 * 1); } } } } data.Msg = "上传完成"; data.Status = 2; } catch (Exception ex) { data.Msg = ex.Message; } return Json(data); }
[HttpPost] public JsonResult ProgresBar02() { var bars = new List<MoBar>(); try { bars = _cache.Get<List<MoBar>>(cacheKey); } catch (Exception ex) { } return Json(bars); }
Task parallel processing + ajax submission + upload progress + a set of image uploads 这一小节,将会使用Task来处理上传的文件,通过上一小节截图能够看出,如果你上传多个文件,那么都是按照次序一个一个读取文件流来生成上传文件到服务器,这里改良一下利用Task的特点,就能实现同时读取不同文件流了,先来看下html代码和js代码: 由于和示例3的js代码无差别这里我直接贴出代码: 关键点在后台,通过task数组来存储每个上传文件的处理任务 Task[] tasks = new Task[len]; ,然后使用 Task.WaitAll(tasks); 等待所有上传任务的完成,这里特别注意了这里必须等待,不然会丢失上传文件流(多次测试结果): 至于获取上传进度的Action也仅仅只是读取缓存数据而已: 这里再给出上传进度的实体类: 到此task任务处理上传文件的方式就完成了,咋们来看图看效果吧: 能够通过示例3和4的效果图对比出,没使用Task和使用的效果区别,这样效果您值得拥有,耐心读完本文内容的朋友,没让你失望吧,如果可以不妨点个"赞"或扫个码支持下作者,谢谢;内容最后附上具体测试用例代码:.NetCore上传多文件的几种示例 The above is the detailed content of Detailed explanation of the example of uploading multiple files using .NetCore. For more information, please follow other related articles on the PHP Chinese website!<form class="form-horizontal" id="form03" method="post" enctype="multipart/form-data">
<input type="file" name="MyPhoto03" class="form-control" multiple />
<br />
<button type="button" id="btnAjax03" class="btn btn-default">task任务处理ajax上传进度效果上传</button>
<br />
<span style="color:red" id="span03"></span>
</form>
$("#btnAjax03").on("click", function () {
var interBar;
var msg = $("#span03");
msg.html("上传中,请稍后...");
var form = document.getElementById("form03");
//console.log(form);
var data = new FormData(form);
$.ajax({
type: "POST",
url: "/home/AjaxFileUp03",
data: data,
contentType: false,
processData: false,
success: function (data) {
if (data) {
msg.html(data.msg);
//清除进度查询
if (interBar) { clearInterval(interBar); }
}
},
error: function () {
msg.html("上传文件异常,请稍后重试!");
if (interBar) { clearInterval(interBar); }
}
});
//获取进度
interBar = setInterval(function () {
$.post("/home/ProgresBar03", function (data) {
if (data) {
var isClearVal = true;
var strArr = [];
$.each(data, function (i, item) {
strArr.push('文件:' + item.fileName + ",当前上传:" + item.percentBar + '<br/>');
if (item.status != 2) { isClearVal = false; }
});
msg.html(strArr.join(''));
if (isClearVal) {
if (interBar) { clearInterval(interBar); }
}
}
});
}, 200);
});
/// <summary>
/// ajax上传进度效果上传
/// </summary>
/// <returns></returns>
[HttpPost]
public JsonResult AjaxFileUp03()
{
var data = new MoData { Msg = "上传失败" };
try
{
var files = Request.Form.Files.Where(b => b.Name == "MyPhoto03");
//非空限制
if (files == null || files.Count() <= 0) { data.Msg = "请选择上传的文件。"; return Json(data); }
//格式限制
var allowType = new string[] { "image/jpeg", "image/png" };
if (files.Any(b => !allowType.Contains(b.ContentType)))
{
data.Msg = $"只能上传{string.Join(",", allowType)}格式的文件。";
return Json(data);
}
//大小限制
if (files.Sum(b => b.Length) >= 1024 * 1024 * 4)
{
data.Msg = "上传文件的总大小只能在4M以下。"; return Json(data);
}
//初始化上传多个文件的Bar,存储到缓存中,方便获取上传进度
var listBar = new List<MoBar>();
files.ToList().ForEach(b =>
{
listBar.Add(new MoBar
{
FileName = b.FileName,
Status = 1,
CurrBar = 0,
TotalBar = b.Length
});
});
_cache.Set<List<MoBar>>(cacheKey03, listBar);
var len = files.Count();
Task[] tasks = new Task[len];
//写入服务器磁盘
for (int i = 0; i < len; i++)
{
var file = files.Skip(i).Take(1).SingleOrDefault();
tasks[i] = Task.Factory.StartNew((p) =>
{
var item = p as IFormFile;
//总大小
var totalSize = item.Length;
//初始化每次读取大小
var readSize = 1024L;
var bt = new byte[totalSize > readSize ? readSize : totalSize];
//当前已经读取的大小
var currentSize = 0L;
var fileName = item.FileName;
var path = Path.Combine(@"D:\F\学习\vs2017\netcore\netcore01\WebApp01\wwwroot\myfile", fileName);
using (var stream = System.IO.File.Create(path))
{
//进度条处理流程
using (var inputStream = item.OpenReadStream())
{
//读取上传文件流
while (inputStream.Read(bt, 0, bt.Length) > 0)
{
//当前读取的长度
currentSize += bt.Length;
//写入上传流到服务器文件中
stream.Write(bt, 0, bt.Length);
//获取每次读取的大小
readSize = currentSize + readSize <= totalSize ?
readSize :
totalSize - currentSize;
//重新设置
bt = new byte[readSize];
//设置当前上传的文件进度,并重新缓存到进度缓存中
var bars = _cache.Get<List<MoBar>>(cacheKey03);
var currBar = bars.Where(b => b.FileName == fileName).SingleOrDefault();
currBar.CurrBar = currentSize;
currBar.Status = currentSize >= totalSize ? 2 : 1;
_cache.Set<List<MoBar>>(cacheKey03, bars);
System.Threading.Thread.Sleep(1000 * 1);
}
}
}
}, file);
}
//任务等待 ,这里必须等待,不然会丢失上传文件流
Task.WaitAll(tasks);
data.Msg = "上传完成";
data.Status = 2;
}
catch (Exception ex)
{
data.Msg = ex.Message;
}
return Json(data);
}
[HttpPost]
public JsonResult ProgresBar03()
{
var bars = new List<MoBar>();
try
{
bars = _cache.Get<List<MoBar>>(cacheKey03);
}
catch (Exception ex)
{
}
return Json(bars);
}
public class MoData
{
/// <summary>
/// 0:失败 1:上传中 2:成功
/// </summary>
public int Status { get; set; }
public string Msg { get; set; }
}
public class MoBar : MoData
{
/// <summary>
/// 文件名字
/// </summary>
public string FileName { get; set; }
/// <summary>
/// 当前上传大小
/// </summary>
public long CurrBar { get; set; }
/// <summary>
/// 总大小
/// </summary>
public long TotalBar { get; set; }
/// <summary>
/// 进度百分比
/// </summary>
public string PercentBar
{
get
{
return $"{(this.CurrBar * 100 / this.TotalBar)}%";
}
}
}