asp.net 다중 파일 업로드를 작성하고 나서 이런 종류의 업로드에는 아직 결함이 많다고 느꼈기 때문에. . . (10,000단어 생략, 말도 안되는 내용은 생략) 여기서는 전통적인 asp.net을 사용하지 않고 오픈소스 asp.net 코어를 선택한 이유는 매우 간단합니다. .net 코어는 .net의 새로운 시작이자 .net과 .net 개발자의 미래입니다. .net이 점점 더 발전하길 바랍니다.
1. 프론트 엔드 구현:
1).html:
<html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <link href="/lib/bootstrap/dist/css/bootstrap.css" rel="external nofollow" rel="stylesheet" /> <script src="/lib/jquery/dist/jquery.js"></script> <script src="/lib/bootstrap/dist/js/bootstrap.js"></script> <script src="/js/UploadJs.js"></script> </head> <body> <p class="row" style="margin-top:20%"> <p class="col-lg-4"></p> <p class="col-lg-4"> <input type="text" value="请选择文件" size="20" name="upfile" id="upfile" style="border:1px dotted #ccc"> <input type="button" value="浏览" onclick="path.click()" style="border:1px solid #ccc;background:#fff"> <input type="file" id="path" style="display:none" multiple="multiple" onchange="upfile.value=this.value"> <br /> <span id="output">0%</span> <button type="button" id="file" onclick="UploadStart()" style="border:1px solid #ccc;background:#fff">开始上传</button> </p> <p class="col-lg-4"></p> </p> </body> </html>
2).javascript:
var UploadPath = ""; //开始上传 function UploadStart() { var file = $("#path")[0].files[0]; AjaxFile(file, 0); } function AjaxFile(file, i) { var name = file.name, //文件名 size = file.size, //总大小shardSize = 2 * 1024 * 1024, shardSize = 2 * 1024 * 1024,//以2MB为一个分片 shardCount = Math.ceil(size / shardSize); //总片数 if (i >= shardCount) { return; } //计算每一片的起始与结束位置 var start = i * shardSize, end = Math.min(size, start + shardSize); //构造一个表单,FormData是HTML5新增的 var form = new FormData(); form.append("data", file.slice(start, end)); //slice方法用于切出文件的一部分 form.append("lastModified", file.lastModified); form.append("fileName", name); form.append("total", shardCount); //总片数 form.append("index", i + 1); //当前是第几片 UploadPath = file.lastModified //Ajax提交文件 $.ajax({ url: "/Upload/UploadFile", type: "POST", data: form, async: true, //异步 processData: false, //很重要,告诉jquery不要对form进行处理 contentType: false, //很重要,指定为false才能形成正确的Content-Type success: function (result) { if (result != null) { i = result.number++; var num = Math.ceil(i * 100 / shardCount); $("#output").text(num + '%'); AjaxFile(file, i); if (result.mergeOk) { var filepath = $("#path"); filepath.after(filepath.clone().val("")); filepath.remove();//清空input file $('#upfile').val('请选择文件'); alert("success!!!"); } } } }); }
여기서 주요 아이디어는 html5 File API의 슬라이스 방법을 사용하여 파일을 덩어리로 나누는 것입니다. 그런 다음 새로운 FormData() 객체를 생성하여 파일 데이터를 저장하고 업로드가 완료될 때까지 AjaxFile 메소드를 반복적으로 호출합니다.
2. 백엔드 C#:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using System.IO; // For more information on enabling MVC for empty projects, visit //m.sbmmt.com/ namespace DotNet.Upload.Controllers { public class UploadController : Controller { // GET: /<controller>/ public IActionResult Index() { return View(); } [HttpPost] public async Task<ActionResult> UploadFile() { var data = Request.Form.Files["data"]; string lastModified = Request.Form["lastModified"].ToString(); var total = Request.Form["total"]; var fileName = Request.Form["fileName"]; var index = Request.Form["index"]; string temporary = Path.Combine(@"E:\浏览器", lastModified);//临时保存分块的目录 try { if (!Directory.Exists(temporary)) Directory.CreateDirectory(temporary); string filePath = Path.Combine(temporary, index.ToString()); if (!Convert.IsDBNull(data)) { await Task.Run(() => { FileStream fs = new FileStream(filePath, FileMode.Create); data.CopyTo(fs); }); } bool mergeOk = false; if (total == index) { mergeOk = await FileMerge(lastModified, fileName); } Dictionary<string, object> result = new Dictionary<string, object>(); result.Add("number", index); result.Add("mergeOk", mergeOk); return Json(result); } catch (Exception ex) { Directory.Delete(temporary);//删除文件夹 throw ex; } } public async Task<bool> FileMerge(string lastModified,string fileName) { bool ok = false; try { var temporary = Path.Combine(@"E:\浏览器", lastModified);//临时文件夹 fileName = Request.Form["fileName"];//文件名 string fileExt = Path.GetExtension(fileName);//获取文件后缀 var files = Directory.GetFiles(temporary);//获得下面的所有文件 var finalPath = Path.Combine(@"E:\浏览器", DateTime.Now.ToString("yyMMddHHmmss") + fileExt);//最终的文件名(demo中保存的是它上传时候的文件名,实际操作肯定不能这样) var fs = new FileStream(finalPath, FileMode.Create); foreach (var part in files.OrderBy(x => x.Length).ThenBy(x => x))//排一下序,保证从0-N Write { var bytes = System.IO.File.ReadAllBytes(part); await fs.WriteAsync(bytes, 0, bytes.Length); bytes = null; System.IO.File.Delete(part);//删除分块 } fs.Close(); Directory.Delete(temporary);//删除文件夹 ok = true; } catch (Exception ex) { throw ex; } return ok; } } }
여기서 아이디어는 먼저 각 청크 파일을 임시 폴더에 저장하고 마지막으로 FileStream을 통해 이러한 임시 파일을 병합합니다(병합은 순서대로 이루어져야 함). 모든 백그라운드 메서드는 비동기식입니다(async wait는 사용하기 매우 쉽습니다). 효율성이 향상되는지는 모르겠지만 멋지다고 생각합니다.
소스코드 다운로드: DotNet_jb51.rar
위 내용은 모두의 학습에 도움이 되기를 바라며, 또한 많은 지원 바랍니다. PHP 중국어 웹사이트.
asp.net 코어 청크 파일 업로드 예제 관련 기사를 더 보려면 PHP 중국어 웹사이트를 주목하세요!