212 lines
7.7 KiB
Plaintext
212 lines
7.7 KiB
Plaintext
= 파일 업/다운로드
|
|
|
|
== 개요
|
|
클라이언트의 파일 업/다운로드 API 호출을 처리한다.
|
|
|
|
=== 파일 업로드
|
|
단일 파일 업로드를 처리한다. 하나의 파일만 업로드하는 경우가 아니라면 보통은 멀티 파일 업로드를 이용한다.
|
|
|
|
=== 멀티 파일 업로드
|
|
|
|
====
|
|
컨트롤러에서 파일 업로드 서비스를 호출한다.
|
|
|
|
.FileManagerController
|
|
[source,java]
|
|
----
|
|
@PostMapping("/resource/attachments/multifile-upload")
|
|
public List<AttachFile> uploadMultiFile(
|
|
@Parameter(description = "MultipartFile[]", required = true) @RequestParam(required = true) MultipartFile[] files,
|
|
@Parameter(description = "다운로드 구분 (컴포넌트 한개 이상일 경우 구분)", required = true) @RequestParam(required = true) String downloadType) {
|
|
|
|
return fileManagerService.save(downloadType, Arrays.asList(files));
|
|
}
|
|
----
|
|
====
|
|
|
|
====
|
|
서비스에서 지정된 경로에 파일 리소스를 저장하고, 업로드된 파일 정보를 DB 에 저장한다.
|
|
|
|
.FileManagerServiceImpl
|
|
[source,java]
|
|
----
|
|
/**
|
|
* 기본 업로드 패스 설정 값
|
|
*/
|
|
@Value("${common.upload-path}")
|
|
private String fileUploadPath;
|
|
|
|
/**
|
|
* 업로드 루트 하위 폴더 자릿수 설정 값
|
|
*/
|
|
@Value("${common.upload.directory-name-len}")
|
|
private int directoryNameLen;
|
|
|
|
/**
|
|
* 사용자지정 업로드 패스 설정 여부
|
|
*/
|
|
@Value("${custom.upload-path.enabled}")
|
|
private boolean customUploadPathEnabled;
|
|
|
|
/**
|
|
* 사용자지정 업로드 패스 설정 값
|
|
*/
|
|
@Value("${custom.upload-path}")
|
|
private String customUploadPaths;
|
|
|
|
@Override
|
|
@Transactional
|
|
public List<AttachFile> save(String downloadType, List<MultipartFile> files) {
|
|
return this.save(downloadType, null, files);
|
|
}
|
|
|
|
@Override
|
|
@Transactional
|
|
public List<AttachFile> save(String downloadType, String refId, List<MultipartFile> files) {
|
|
List<AttachFile> attachFileList = new ArrayList<>();
|
|
|
|
files.stream().forEach(file -> {
|
|
AttachFile attachFile = this.save(downloadType, refId, file);
|
|
attachFileList.add(attachFile);
|
|
});
|
|
|
|
return attachFileList;
|
|
}
|
|
|
|
@Override
|
|
@Transactional
|
|
public AttachFile save(String downloadType, String refId, MultipartFile file) {
|
|
String fileId = this.store(file, downloadType); // <1>
|
|
|
|
AttachFile attachFile = new AttachFile();
|
|
attachFile.setDownloadType(downloadType);
|
|
attachFile.setFilePathName(this.rootUploadPath.toString());
|
|
attachFile.setFileExtensionName(fileId);
|
|
attachFile.setFileName(file.getOriginalFilename());
|
|
attachFile.setFileMimeTypeName(file.getContentType());
|
|
attachFile.setFileSize(file.getSize());
|
|
attachFile.setOwnerObjectPkId(refId);
|
|
|
|
return fileManagerDao.insertFileInfo(attachFile); // <2>
|
|
}
|
|
----
|
|
<1> 파일 리소스 저장
|
|
<2> 업로드된 파일 정보 DB저장
|
|
====
|
|
|
|
====
|
|
파일 리소스 저장 경로는 기본 업로드 패스 값(common.upload-path)과 하위 디렉토리 길이 설정 값(common.upload.directory-name-len)에 따라 결정된다. +
|
|
기본 업로드 패스외에 사용자정의 업로드 패스 설정도 가능하다.
|
|
|
|
.config.properties
|
|
[source,properties]
|
|
----
|
|
## File Attach Configuration
|
|
common.upload-path=/NAS/SDL/upload // <1>
|
|
common.upload.directory-name-len=2 // <2>
|
|
# custom upload path 설정
|
|
custom.upload-path.enabled=false // <3>
|
|
custom.upload-path=\ // <4>
|
|
notice=/NAS/SDL/upload/notice,\
|
|
faq=/NAS/SDL/upload/faq
|
|
----
|
|
<1> 기본 업로드 패스 설정
|
|
<2> 업로드 패스 하위 디렉토리 길이 +
|
|
파일명(UUID)에서 이 길이 만큼 잘라서 기본 업로드 패스 하위 디렉토리가 생성된다.
|
|
<3> 사용자정의 업로드 패스 사용 여부
|
|
<4> 파일 컴포넌트별 사용자정의 업로드 패스 설정 (custom.upload-path.enabled=true 일 경우 적용됨)
|
|
====
|
|
|
|
=== 파일 다운로드
|
|
컨트롤러에서 파일 다운로드 서비스를 호출한다.
|
|
|
|
.FileManagerController
|
|
[source,java]
|
|
----
|
|
@GetMapping("/resource/attachments/file-download/{fileId}")
|
|
public ResponseEntity<Resource> downloadFile(
|
|
@Parameter(description = "File ID", required = true) @PathVariable String fileId,
|
|
@Parameter(description = "다운로드 구분 (컴포넌트 한개 이상일 경우 구분)", required = true) @RequestParam(required = true) String downloadType,
|
|
HttpServletRequest request) {
|
|
|
|
long startTime = System.nanoTime();
|
|
|
|
if (StringUtils.isBlank(fileId)) {
|
|
throw new FileManagerException("No File ID");
|
|
}
|
|
|
|
AttachFile attachFile = fileManagerService.getAttachFile(fileId, downloadType); // <1>
|
|
if (attachFile == null) {
|
|
throw new FileManagerException("Cannot find file info: " + fileId);
|
|
}
|
|
Resource resource = fileManagerService.getResource(attachFile.getFileExtensionName(), attachFile.getFilePathName()); // <2>
|
|
|
|
String contentType = attachFile.getFileMimeTypeName();
|
|
if (StringUtils.isBlank(contentType)) {
|
|
contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
|
}
|
|
|
|
String fileName = attachFile.getFileName(); // <3>
|
|
String encodeFileName = null;
|
|
// 다운로드 파일명 UTF-8 인코딩
|
|
encodeFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("+", "%20");
|
|
|
|
// 다운로드 이력 로깅
|
|
fileManagerService.saveFileDownloadLog(fileName, startTime, request); // <4>
|
|
|
|
return ResponseEntity.ok()
|
|
.contentType(MediaType.parseMediaType(contentType))
|
|
.header("Content-Transfer-Encoding", "binary")
|
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodeFileName + "\"")
|
|
.body(resource);
|
|
}
|
|
----
|
|
<1> 파일 정보 조회
|
|
<2> 파일 리소스 가져오기
|
|
<3> 파일 업로드 시점의 파일명
|
|
<4> 파일 다운로드 이력 로깅
|
|
|
|
=== 멀티 파일 다운로드
|
|
여러 파일을 zip 파일 형태로 다운로드할 수 있도록 제공한다.
|
|
|
|
.FileManagerController
|
|
[source,java]
|
|
----
|
|
@Value("${common.download.zipfilename}")
|
|
private String zipFileName;
|
|
|
|
@GetMapping("/resource/attachments/multifile-download")
|
|
public ResponseEntity<ByteArrayResource> downloadMultiFile(
|
|
@Parameter(description = "File IDs", required = true) @RequestParam(required = true) String[] fileIds,
|
|
@Parameter(description = "다운로드 구분 (컴포넌트 한개 이상일 경우 구분)", required = true) @RequestParam(required = true) String downloadType,
|
|
@Parameter(description = "zip 파일명", required = false) @RequestParam(required = false) String zipFileName,
|
|
HttpServletRequest request) {
|
|
|
|
long startTime = System.nanoTime();
|
|
|
|
if (fileIds == null || fileIds.length == 0) {
|
|
throw new FileManagerException("No File ID(s)");
|
|
}
|
|
|
|
if (StringUtils.isBlank(zipFileName)) {
|
|
zipFileName = this.zipFileName;
|
|
}
|
|
|
|
// 다운로드 파일명 UTF-8 인코딩
|
|
String fileName = null;
|
|
fileName = URLEncoder.encode(zipFileName, StandardCharsets.UTF_8).replace("+", "%20");
|
|
|
|
// 다운로드 이력 로깅
|
|
fileManagerService.saveFileDownloadLog(zipFileName, startTime, request);
|
|
|
|
ByteArrayResource baResource = fileManagerService.getByteArrayResource(fileIds, downloadType);
|
|
|
|
return ResponseEntity.ok()
|
|
.contentLength(baResource.contentLength())
|
|
.contentType(MediaType.parseMediaType("application/zip"))
|
|
.header("Content-Transfer-Encoding", "binary")
|
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + ".zip\";")
|
|
.body(baResource);
|
|
}
|
|
----
|