[ASP.NET/MVC CORE] #10 파일 업로드 기능 구현

안녕하세요 미나라이입니다.
이번에는 ASP.NET CORE MVC Web의 파일 업로드 기능을 구현하는 방법에 대해서 포스팅 하려고 합니다.
프로젝트 환경
OS : Windows 10
IDE : Visual Studio Code 1.62.2
.Net SDK : 5.0.403
.Net Runtime : .NetCore.App 5.0.10 / 5.0.12
클라이언트
클라이언트에는 업로드 할 파일을 등록하는 작업을 수행합니다.
Index.cshtml
CSS
#dragDropArea{
background-color: #f4f4f4;
margin: 10px;
padding: 10px;
border: #ddd solid 2px;
min-height: 200px;
text-align: center;
border-radius: 5px;
}
#dragDropArea p{
color: #999;
font-weight: bold;
font-size: 14px;
font-size: 1.4em;
}
#dragDropArea .drag-drop-buttons{
margin-top: 20px;
font-size: 12px;
font-size: 1.2em;
}
.drag-drop-buttons input{
margin: auto;
}
.fileInputButton {
color: white;
background-color: lightgray;
padding: 10px;
border-radius: 10px;
cursor:pointer;
color:#999;
}
HTML
<!-- Jquery 라이브러리 -->
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<div class="Container">
<div id="dragDropArea">
<div class="drag-drop-inside">
<p class="drag-drop-info">여기에 파일을 드래그 앤드 드롭</p>
<p>또는</p>
<p class="drag-drop-buttons">
<label class="fileInputButton">
+ 첨부 파일 선택
<input id="fileInput" type="file" style="display:none;" multiple="multiple" onchange="javascript:fnSelectFile();"></input>
</label>
</p>
<div id="fileList" style="text-align:center;"></div>
</div>
</div>
<button type="button" class="btn btn-primary btn-block" onclick="javascript:fnSendFile();">Upload</button>
</div>
화면 예시
ASP.NET CORE MVC프로젝트에서는 Bootstrap라이브러리를 기본적으로 제공 해 주고 있기 때문에 바로 사용 가능합니다.
라이브러리 정의는 _Layout.cshtml 파일에 있습니다.

Javascript / Jquery
스크립트 부분입니다.
Ajax처리는 Jquery를 이용했기 때문에 Jquery라이브러리가 필요합니다.
파일 업로드 최대 사이즈를 10메가로 설정해놓았습니다.
값을 변경해서 최대 사이즈를 조정 할 수 있습니다.
var _FormData = new FormData(); // 서버 전송 폼 변수
var _FILE_MAX_SIZE = 10; // 업로드 파일 최대 사이즈
window.onload = function() {
// 드래그 앤드 드롭 이벤트가 일어나는 태그
var fileArea = document.getElementById('dragDropArea');
// 첨부파일 Input태그
var fileInput = document.getElementById('fileInput');
// 파일을 드래그 해서 범위 안에 두었을 때 발생하는 이벤트
fileArea.addEventListener('dragover', function (evt) {
evt.preventDefault();
fileArea.classList.add('dragover');
});
// 드래그 한 파일을 범위 밖으로 가져 갈 때 발생하는 이벤트
fileArea.addEventListener('dragleave', function (evt) {
evt.preventDefault();
fileArea.classList.remove('dragover');
});
// 드래그 한 파일을 범위 안에 두고 마우스를 떼었을 때 발생하는 이벤트
fileArea.addEventListener('drop', function (evt) {
evt.preventDefault();
fileArea.classList.remove('dragenter');
// 드래그 한 파일 정보를 가져오는 부분
var files = evt.dataTransfer.files;
// 첨부파일 Input태그에 드래그 한 파일을 적용
fileInput.files = files;
// 파일 선택 확인 함수 호출
fnSelectFile();
});
}
// 파일 선택 확인
function fnSelectFile() {
// 파일 사이즈 확인
var maxsize = _FILE_MAX_SIZE * 1024 * 1024;
// 첨부파일 Input태그 호출
var input = document.getElementById('fileInput');
// Input 태그에서 선택된 파일 개수 만큼 반복
for (var i = 0; i < input.files.length; ++i) {
var name = input.files.item(i).name; // 파일명
var size = input.files.item(i).size; // 파일 사이즈
// 파일 사이즈 체크
if(size > maxsize) {
alert("파일은 " + _FILE_MAX_SIZE + "Byte 이하만 가능합니다.");
}
else {
// 폼 데이터에 파일 정보 보존
_FormData.append("files", input.files[i]);
}
}
// 선택 파일을 화면에 표시
fnDisplayFileList();
}
// 선택한 파일을 삭제
function fnCancelFile(name, size) {
// 폼 데이터의 파일 정보 취득
var filelist = _FormData.getAll("files");
// 폼 데이터의 파일 정보 삭제
_FormData.delete("files");
// 취득한 파일 정보 개수 만큼 반복
for(var file of filelist) {
// 삭제 대상 파일인 경우 스킵
if(file.name == name && file.size == size) {
continue;
}
// 폼 데이터에 파일 정보를 다시 보존
_FormData.append("files", file);
}
// 선택 파일을 화면에 표시
fnDisplayFileList();
}
// 선택 파일을 화면에 표시
function fnDisplayFileList() {
var children = "";
var output = document.getElementById('fileList');
filelist = _FormData.getAll("files");
for(var file of filelist) {
var name = file.name;
var size = file.size;
children += '📎 ' + name + ' ';
children += "<span style='cursor:pointer;color:red;' onclick='javascript:fnCancelFile(\"" + name + "\", " + size +");'>✖</span><Br />";
}
// 추가되는 파일 목록 태그를 HTML에 적용
output.innerHTML = children;
}
// 파일 업로드 작업
function fnSendFile() {
$.ajax({
url: '/Home/FileUpload',
type: "POST",
contentType: false,
processData: false,
data: _FormData,
async: false,
success: function (data) {
if(data.result == 0) {
// 파일 업로드 후 리스트 초기화
alert("파일 업로드 완료!");
// 컨트롤러 메인 페이지로 이동
window.location.href = "/Home";
}
else {
alert("파일 업로드 실패!");
}
},
error: function (err) {
// 에러일 경우 에러 메세지 출력
alert(err.statusText);
}
});
}
파일 등록 후
파일 이름 우측의 X 버튼을 누르면 등록 한 파일이 지워집니다.

10메가 이상의 파일을 업로드 했을 경우 메세지 표시

서버
서버 부분에서는 클라이언트에서 등록한 파일을 실제 서버에 업로드 처리를 진행합니다.
화면의 Upload 버튼을 누르면 컨트롤러로 넘어옵니다.
HomeController.cs
비동기 처리를 위해서 Task기능을 사용하였습니다.
자세한 설명은 아래 링크
C#의 비동기 프로그래밍
async, await 및 Task를 사용하여 비동기 프로그래밍을 지원하는 C# 언어에 대해 간략히 설명합니다.
docs.microsoft.com
using System;
using System.IO;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
public async Task<JsonResult> FileUpload(IList<IFormFile> files)
{
int result = -1;
string uploadDir = "C:/workspace/dotnet/UploadPath/";
try
{
// 업로드 폴더 경로 존재 확인
DirectoryInfo di = new DirectoryInfo(uploadDir);
// 폴더가 없을 경우 신규 작성
if(di.Exists == false) di.Create();
// 선택한 파일 개수만큼 반복
foreach (var formFile in files)
{
if (formFile.Length > 0)
{
var fileFullPath = uploadDir + formFile.FileName;
// 파일명이 이미 존재하는 경우 파일명 변경
int filecnt = 1;
String newFilename = string.Empty;
while(new FileInfo(fileFullPath).Exists)
{
var idx = formFile.FileName.LastIndexOf('.');
var tmp = formFile.FileName.Substring(0, idx);
newFilename = tmp + String.Format("({0})",filecnt++) + formFile.FileName.Substring(idx);
fileFullPath = uploadDir + newFilename;
}
// 파일 업로드
using (var stream = new FileStream(fileFullPath, FileMode.CreateNew))
{
await formFile.CopyToAsync(stream);
}
}
}
result = 0;
}
catch(Exception)
{
throw;
}
return Json(new { result = result });
}
업로드 결과

파일 확인

샘플 프로젝트를 첨부합니다.
이상으로 간단하게 MVC환경에서 파일을 업로드 하는 기능에 대해서 알아보았습니다.
'ASP.NET&C# > ASP.NET MVC' 카테고리의 다른 글
[ASP.NET CORE/MVC] #12 AJAX로 JSON데이터를 컨트롤러로 전송하기 (0) | 2021.12.18 |
---|---|
[ASP.NET CORE/MVC ] #11 VIEW파일 분할해서 보여주기(Partial) (0) | 2021.12.15 |
[ASP.NET CORE/MVC] #9 파일 다운로드 기능 구현 (0) | 2021.12.13 |
[ASP.NET CORE/MVC] #8 AJAX를 이용해서 컨트롤러로 데이터 주고 받기 (1) | 2021.12.12 |
[ASP.NET CORE/MVC] #7 컨트롤러로 데이터 보내고 받기 (1) | 2021.12.11 |