최근 프로젝트를 진행하며 ZIP 파일을 생성해서 서버올릴 일이 있어 이것저것 구글링 하던도중
MemoryStream,
ZipArchive,
FileStream 을 통해 구성하는 법으로 구현해 보았다.
기존의 서버에 올라가있는 여러개의 이미지 파일을 묶어 서버로 zip file로 생성하고 저장 해보자.
1. 코드
[HttpGet]
[Route("api/zipUpload")]
public async Task<HttpResponseMessage> SetFileZip()
{
//서버에 폴더있는지 조회, 없으면 생성
DirectoryInfo dir = new DirectoryInfo(HttpContext.Current.Server.MapPath("/data/zip/"));
if (!dir.Exists)
{
dir.Create();
}
List<string> fileList = new List<string>();
/*
* fileList - file명으로 채워주기
*
*/
string zipFileName = HttpContext.Current.Server.MapPath("/data/zip/"
+ DateTime.Now.ToString("yyyyMMddHHmmss") + ".zip");
string[] archiveFileList = new string[fileList.Count];
for (int i = 0; i < fileList.Count; i++)
{
FileInfo file = new FileInfo(HttpContext.Current.Server.MapPath("/data/" + fileList[i]));
if (file.Exists)
{
//저장
archiveFileList[i] = HttpContext.Current.Server.MapPath("/data/" + fileList[i]);
}
else
{
//서버에 파일존재하지 않음
return Request.CreateResponse(HttpStatusCode.NotFound);
}
}
using (var ms = new MemoryStream())
{
// archive log files
using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
foreach (var f in archiveFileList)
{
//photo 하위 폴더 directory지정
var zipEntity = archive.CreateEntry(f);
using (var entryStream = zipEntity.Open())
using (var readStream = File.OpenRead(f))
{
await readStream.CopyToAsync(entryStream);
}
}
};
// write archived data
using (var fs = new FileStream(zipFileName, FileMode.Create))
{
// 스트림의 맨끝
ms.Seek(0, SeekOrigin.Begin);
await ms.CopyToAsync(fs);
}
}
return Request.CreateResponse(HttpStatusCode.OK);
}
프로젝트를 하면서 이런 로직으로 구현해 보았고 다행히 문제없이 구현한다.
실제로 사용했을 때는 동일한 Title 데이터 값으로 Img들이 몇개씩 그룹화 되어 있었기 때문에 Title값으로 Image명을 가져와 ZIP파일로 만들어주었다.
2. 실제 구현
ajax를 통해 본 API를 활용해 서버 올려본 결과 (지저분해서 죄송합니다 ㅎㅎ...)
성공적으로 작동하는 것을 볼 수 있다.
프론트에서 본 api를 호출해서 사용하면 된다.
$('input:checkbox[name="chkIdx"]').each(function () {
if (this.checked) {
$.ajax({
url: "/api/zipUpload",
success: function (message) {
//업로드 성공 시 로직
},
error: function (message) {
if (message != 200) {
alert("파일이 존재하지 않습니다.");
}
location.href = "URL";
return false;
}
});
};
});
alert("Complete!");
location.reload();
});
저같은 경우는 체크한 값들을 매개변수로 붙여서 Get방식으로 처리해주었는데 필요할 경우 바꾸시면 됩니다.
3. 압축파일 명에 특수기호가 들어갈 시 처리
Title값에 특수기호가 들어가있어서 api에서 제거 로직을 추가해줬는데
new string(title.Select(c => char.IsLetterOrDigit(c) ? c : '_').ToArray()).Trim();
을 통해서 특수문자 부분을 '_' 언더바로 간단하게 변환할 수 있었습니다.
4. 서버 업로드 이유
클라이언트에서 ZIP파일을 다운로드 받을 때 서버에서 파일을 찾아 ZIP파일로 위와같은 과정을 거쳐 만들고 바로 다운로드 받으면 되지 않나? 라는 의문을 가질텐데,
그렇게 되면 매번 ZIP파일을 만드는 과정을 반복하기 때문에 성능적인 측면에서 문제가 있다. 때문에 시작하는 프로젝트라면 업로드시에 서버에 ZIP파일을 저장소를 만들고 미리 저장해서 보관해 놨다가 클라이언트에서 요청시 압축 작업없이 다운로드만 바로 받을 수 있게 해서 성능과 속도적인 측면에서 유리하게 가져간다.
만약에 이번과 같이 운영중인 프로젝트라면 이전까지의 자료를 압축작업을 일일히 하기 방대하므로, 서버에 파일이 올라갈시, 수정작업시 ZIP파일을 만듦과 동시에 클라에서 맨 처음 ZIP 다운로드 요청시 1회에 한해 ZIP파일 압축과정을 거쳐 서버에 올리도록 한다.
다음은 다운로드를 해보자.
'Web > .NET Core C#' 카테고리의 다른 글
[.NET] 비동기 ZIP File Download API (서버 올리기) (0) | 2021.01.06 |
---|