. NetCore 에서 여러 파일 을 업로드 하 는 몇 가지 예시

이 장 에서 여러분 과 공유 하 는 것 은. NetCore 의 MVC 프레임 워 크 업로드 파일 의 예제 입 니 다. 주로 form 방식 으로 업로드, ajax 업로드, ajax 제출 + 업로드 진도 효과, Task 병행 처리 + ajax 제출 + 업로드 진도 가 있 습 니 다. 글 내용 을 읽 고 좋 은 수확 을 얻 을 수 있 을 것 이 라 고 믿 습 니 다. 좋아요 를 누 르 셔 도 됩 니 다.어제 컴퓨터 가 배터리 가 없어 서 다 쓴 내용 이 저장 되 지 않 았 습 니 다. 오늘 아침 에 미리 회사 에 와 서 처음부터 다시 시작 합 니 다. 전기 가 끊 기 는 상황 은 정말 골 치 아 픕 니 다. 하지만 지역 사회의 공유 환경 을 위해 서도 가치 가 있 습 니 다. 더 이상 말 하지 않 고 오늘 의 본 부분 에 들 어 가 겠 습 니 다.
form 방식 으로 그림 업로드
html 코드 부터 살 펴 보 겠 습 니 다. 파일 을 업로드 하려 면 form 요소 안에 있 는 것 을 설정 해 야 합 니 다. enctype="multipart/form-data" 속성 과 post 방식 입 니 다. 파일 업로드 방식 을 더 선택 하려 면 파일 type = 'file' 요 소 를 속성 multiple = 'multiple' 로 설정 해 야 합 니 다. 따라서 다음 과 같은 내용 이 있 습 니 다.
                               
                               
               @ViewData["MsgBox"]            

由于采用form提交,这个测试用例只接用了button元素默认的type=submit来提交表单,对应的后台Action中代码如下:

/// 
        /// form    
        /// 
        /// 
        /// 
        [HttpPost]
        public async Task 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[] { "p_w_picpath/jpeg", "p_w_picpath/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
etcore
etcore01\WebApp01\wwwroot\myfile", fileName);                 using (var stream = System.IO.File.Create(path))                 {                     await file.CopyToAsync(stream);                 }             }             MsgBox($" ");             return View();         }

전단 에서 백 엔 드 까지 의 Action 은 이러한 form 폼 을 제출 하 는 방식 이 매우 간단 하 다 고 말 할 수 밖 에 없다. 주의해 야 할 것 은 Action 에서 사용 하 는 실제 모델 방식 으로 업 로드 된 파일 정보 에 대응 하 는 것 이다. 여 기 는 MoUser 류 를 사용자 정의 하고 속성 을 통 해 public List MyPhoto { get; set; } html 폼 의 파일 type = 'file' 과 일치 하 는 name 속성 이름 name = "MyPhoto":
public class MoUser
    {
        public int UserId { get; set; } = 1;
        public string UserName { get; set; } = "    3";

        public List MyPhoto { get; set; }
    }

이렇게 하면 실제 모델 을 통 해 업 로드 된 파일 정 보 를 사용자 정의 MoUser 클래스 의 MyPhoto 속성 에 저장 할 수 있 습 니 다.
ajax 사진 업로드
이 곳 은 위의 예 에서 html 에서 뭔 가 를 수정 해 야 합 니 다. form 으로 제출 하지 않 고 일반 button 단 추 를 지정 하여 ajax 의 제출 을 촉발 합 니 다. 전체 html 코드 는 다음 과 같 습 니 다.
                                 
                                 
                             

有了布局,再来看看具体的js实现代码,这里我采用jquery的ajax提交的方法来操作,也用到了html5新增的FormData来存储表单的数据:

$("#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("      ,     !");
                }
            });
        });

백 스테이지 Action 의 방법 과 예시 1 의 차이 가 크 지 않 습 니 다. 관건 은 여기 서 제 가 직접 사용 하 는 것 입 니 다. Request.Form.Files 업로드 한 모든 파일 을 가 져 오 는 방식 입 니 다. 더 이상 실체 모델 을 사용 하지 않 습 니 다. 그러면 테스트 사례 가 더욱 다양 해 집 니 다.
/// 
        /// ajax         
        /// 
        /// 
        [HttpPost]
        public async Task 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[] { "p_w_picpath/jpeg", "p_w_picpath/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
etcore
etcore01\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 제출 + 업로드 진도 + 그림 업로드
마찬가지 로 우리 가 먼저 대응 하 는 html 코드 를 보 았 는데 사실은 예시 2 와 거의 같 아서 이름 만 바 꾸 었 다.

                
                
                                 
                             

要加一个进度效果,需要用到js的定时器,定时获取上传文件的上传进度数据信息,因此这里通过js的setInterval方法来定时请求一个进度数据接口,注意用完之后需要清除这个定时器,不然一直再不断请求您接口:

$("#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 + '
');                             if (item.status != 2) { isClearVal = false; }                         });                         msg.html(strArr.join(''));                         if (isClearVal) {                             if (interBar) { clearInterval(interBar); }                         }                     }                 });             }, 200);         });

위 에서 단독 진도 데이터 인터페이스 라 고 말 한 이상 저 희 는 Action 을 업로드 하 는 것 외 에 진도 의 Action 도 필요 합 니 다. 이 진도 Action 이 얻 은 업로드 파일 데이터 정 보 는 반드시 업로드 한 Action 과 계속 해 야 하기 때문에 캐 시 등 데 이 터 를 저장 하 는 방식 을 사용 해 야 합 니 다. 여 기 는 Memory Cache 방식 을 사용 합 니 다. 이미 netcore 에 있어 서 시작 파일 만 사용 해 야 합 니 다.(예: Startup. cs) 에 구성 요소 서비스 추가:
public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddMvc();

            //  cache  
            services.AddDistributedMemoryCache();
        }

그리고 구조 함 수 를 통 해 대응 하 는 인터페이스 Controller 에 주입 합 니 다.
readonly IMemoryCache _cache;

        public HomeController(IOptions options, ILogger logger, IMemoryCache cache)
        {
            this._options = options.Value;
            _logger = logger;
            _cache = cache;
        }

여기 서 우 리 는 cache 를 이용 하여 우리 가 업로드 한 진도 정 보 를 저장 할 수 있 습 니 다. 업로드 한 Action 을 처리 하 는 것 을 보 겠 습 니 다.
private string cacheKey = "UserId_UpFile";
        private string cacheKey03 = "UserId_UpFile03";
        /// 
        /// ajax        
        /// 
        /// 
        [HttpPost]
        public async Task 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[] { "p_w_picpath/jpeg", "p_w_picpath/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();
                files.ToList().ForEach(b =>
                {
                    listBar.Add(new MoBar
                    {
                        FileName = b.FileName,
                        Status = 1,
                        CurrBar = 0,
                        TotalBar = b.Length
                    });
                });
                _cache.Set>(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
etcore
etcore01\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>(cacheKey);                                 var currBar = bars.Where(b => b.FileName == fileName).SingleOrDefault();                                 currBar.CurrBar = currentSize;                                 currBar.Status = currentSize >= totalSize ? 2 : 1;                                 _cache.Set>(cacheKey, bars);                                 System.Threading.Thread.Sleep(1000 * 1);                             }                         }                     }                 }                 data.Msg = " ";                 data.Status = 2;             }             catch (Exception ex)             {                 data.Msg = ex.Message;             }             return Json(data);         }

코드 가 한꺼번에 많아 졌 습 니 다. 사실은 논리 적 으로 저장 진도 의 Cache 를 추 가 했 고 업로드 파일 흐름 의 논 리 를 하나씩 읽 었 을 뿐 입 니 다. 구체 적 으로 코드 를 자세히 볼 수 있 습 니 다. 모두 비고 설명 이 있 습 니 다. 그리고 어떻게 진행 하 는 지 정보 Action 인터페이스 입 니 다.
[HttpPost]
        public JsonResult ProgresBar02()
        {
            var bars = new List();
            try
            {
                bars = _cache.Get>(cacheKey);
            }
            catch (Exception ex)
            {
            }
            return Json(bars);
        }

진도 인 터 페 이 스 는 cache 의 진도 정 보 를 얻 기만 하면 됩 니 다. 주: 여 기 는 테스트 사례 입 니 다. 구체 적 으로 장면 을 사용 할 때 여러분 은 스스로 다른 논리 코드 를 추가 하 십시오. 다음은 효과 캡 처 를 보 겠 습 니 다.
작업 병행 처리 + ajax 제출 + 업로드 진도 + 그림 업로드
이 소절 은 Task 를 사용 하여 업 로드 된 파일 을 처리 할 것 입 니 다. 이전 소절 캡 처 를 통 해 알 수 있 듯 이 여러 개의 파일 을 업로드 하면 순서대로 파일 흐름 을 읽 어 서버 에 업로드 파일 을 생 성 합 니 다. 여기 서 Task 의 특징 을 개량 하면 서로 다른 파일 흐름 을 동시에 읽 을 수 있 습 니 다. 먼저 html 코드 와 js 코드 를 살 펴 보 겠 습 니 다.

                
                
                                 
                             

由于和示例3的js代码无差别这里我直接贴出代码:

$("#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 + '
');                             if (item.status != 2) { isClearVal = false; }                         });                         msg.html(strArr.join(''));                         if (isClearVal) {                             if (interBar) { clearInterval(interBar); }                         }                     }                 });             }, 200);         });

관건 은 배경 에 있 습 니 다. task 배열 을 통 해 모든 업로드 파일 의 처리 작업 을 저장 합 니 다. Task[] tasks = new Task[len]; ,그리고 사용 Task.WaitAll(tasks); 모든 업로드 작업 이 완료 되 기 를 기다 리 고 있 습 니 다. 여기 서 기 다 려 야 합 니 다. 그렇지 않 으 면 업로드 파일 흐름 (여러 번 테스트 결과) 을 잃 어 버 릴 수 있 습 니 다.
/// 
        /// ajax        
        /// 
        /// 
        [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[] { "p_w_picpath/jpeg", "p_w_picpath/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();
                files.ToList().ForEach(b =>
                {
                    listBar.Add(new MoBar
                    {
                        FileName = b.FileName,
                        Status = 1,
                        CurrBar = 0,
                        TotalBar = b.Length
                    });
                });
                _cache.Set>(cacheKey03, listBar);

                var len = files.Count();
                Task[] tasks = new Task[len];
                //       
                for (int i = 0; i 
                    {
                        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
etcore
etcore01\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>(cacheKey03);                                     var currBar = bars.Where(b => b.FileName == fileName).SingleOrDefault();                                     currBar.CurrBar = currentSize;                                     currBar.Status = currentSize >= totalSize ? 2 : 1;                                     _cache.Set>(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);         }

업로드 진 도 를 가 져 오 는 Action 도 캐 시 데이터 만 읽 을 뿐 입 니 다.
[HttpPost]
        public JsonResult ProgresBar03()
        {
            var bars = new List();
            try
            {
                bars = _cache.Get>(cacheKey03);
            }
            catch (Exception ex)
            {
            }
            return Json(bars);
        }

업로드 진도 의 실체 클래스 를 보 여 줍 니 다:
public class MoData
    {
        /// 
        /// 0:   1:    2:  
        /// 
        public int Status { get; set; }

        public string Msg { get; set; }
    }

    public class MoBar : MoData
    {
        /// 
        ///     
        /// 
        public string FileName { get; set; }

        /// 
        ///       
        /// 
        public long CurrBar { get; set; }

        /// 
        ///    
        /// 
        public long TotalBar { get; set; }

        /// 
        ///      
        /// 
        public string PercentBar
        {
            get
            {
                return $"{(this.CurrBar * 100 / this.TotalBar)}%";
            }
        }
    }

이 task 작업 은 파일 업로드 방식 을 처리 하면 됩 니 다. 그림 을 보고 효 과 를 봅 시다.
예시 3 과 4 의 효과 도 를 통 해 Task 를 사용 하지 않 은 것 과 사용 한 효과 의 차 이 를 비교 할 수 있 습 니 다. 이러한 효 과 는 당신 이 가 질 만 한 가치 가 있 습 니 다. 인내심 을 가지 고 본문 내용 을 읽 은 친 구 는 실망 시 키 지 않 았 습 니 다. 만약 에 '좋아요' 를 누 르 거나 코드 를 스 캔 하여 작 가 를 지원 할 수 있다 면 감사합니다.

좋은 웹페이지 즐겨찾기