파일 복사, 바이트 읽기/쓰기 등에 특화된 간단한 유틸
// 파일 → byte[]
byte[] bytes = FileCopyUtils.copyToByteArray(new File("sample.txt"));
// InputStream → byte[]
byte[] bytes2 = FileCopyUtils.copyToByteArray(inputStream);
// byte[] → OutputStream
FileCopyUtils.copy(bytes, outputStream);
업로드된 파일 처리용 인터페이스 (파일명, 크기, 스트림 등 접근 가능)
String fileName = multipartFile.getOriginalFilename();
byte[] content = multipartFile.getBytes();
multipartFile.transferTo(new File("C:/upload/" + fileName));
클래스패스 리소스, 외부파일 리소스 등 통합 접근
@Autowired
ResourceLoader resourceLoader;
Resource resource = resourceLoader.getResource("classpath:static/sample.txt");
InputStream is = resource.getInputStream();
Stream ↔ byte[], String 간 변환
String text = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
byte[] bytes = StreamUtils.copyToByteArray(inputStream);
InputStream is = servletContext.getResourceAsStream("/WEB-INF/sample.txt");
목적 | 추천 유틸 클래스 |
---|---|
파일 복사 / 바이트 I/O | FileCopyUtils |
업로드 파일 처리 | MultipartFile |
클래스패스 리소스 읽기 | Resource , ResourceLoader |
Stream to String 변환 | StreamUtils |
그래서 스프링제공 유틸클래스로 기존 스케줄러 로직을 바꿔봄
try (InputStream fis = new FileInputStream(file))
InputStream 열고
byte[] data = StreamUtils.copyToByteArray(fis);
바이트로 변환
.
.
.
.
vo 로 insert하기위한 set vo
service 로직에서 file을 이동시킬때 에러가 났는데...(트랜잭션처리를위해 서비스단으로 분리시켰었음)
Caused by: java.nio.file.FileSystemException:
다른 프로세스가 파일을 사용 중이기 때문에 프로세스가 액세스 할 수 없습니다.
서비스 호출하는 스케줄러 로직에서 InputStream 을 열어놓고 닫히지 않는상태에서 Files.move 를하려함
그래서 finally 에 close() 후
finally {
if(vo != null)
fileService.insertBinaryFile(vo, file);
}
insert 하게 수정
바뀐
로직:
File[] files =dir.listFiles(); // 파일 리스트 가져옴
if(files !=null){
for(File file : files) {
if(file.isFile()){
FileVO vo = new FileVO();
try{
try (InputStream fis = new FileInputStream(file)){
// 스프링제공 stream utils
// file => byte 변환
byte[] data = StreamUtils.copyToByteArray(fis);
// byte -> String 변환
// String content = StreamUtils.copyToString(fis, StandardCharsets.UTF_8);
// ㄴ> stream 이 두번열리면 안된다함
//그래서 일케바꿔야함
String content = new String(data,StandardCharsets.UTF_8);
log.info("처리중 파일 : " + file.getName());
// 시퀀스 받아오기
vo.setFileId(fileService.getFileId());
vo.setFileName(file.getName());
vo.setFileType("application/octet-stream"); // 파일의 MIME 타입지정 - 바이너리파일이라는뜻
vo.setFileData(data); // 스프링 IO
// vo.setFileData(filesdata); // NIO
vo.setFileDataInfo(content);
} catch (IOException e) {
throw new RuntimeException("StreamUtils error",e);
} finally {
if(vo != null)
fileService.insertBinaryFile(vo, file);
}
} catch (Exception e) {
e.printStackTrace();
if(!failDir.exists()) failDir.mkdir();
Files.move(Paths.get(file.getPath()), Paths.get(failDir.getPath(), vo.getFileName()));
log.info("업로드실패로인한 파일 실패경로 이동" + file.getName());
}
}
}
}
try(OutputStream os = new FileOutputStream(target)){
OutStream 열고 target파일은 파일명 중복체크한 결과 파일
StreamUtils.copy(vo.getFileDataInfo(),StandardCharsets.UTF_8, os);
이 줄을 추가함
디비에 저장된 바이너리파일의 데이터값이 있는경우에만 다운로드 하게 바꿨음
-> if(!StringUtils.isEmpty(vo.getFileDataInfo())){
이 줄을 try 위로 빼줬다.
try에서 OutStream을열었기때문에 try안에 null체크를 해봤자 무조건생성이되어버림
디비에 blob형태 파일이 있으면 그냥 바로
StreamUtils.copy(vo.getFileData(),os);
@Scheduled(cron = "0 0/5 * * * ?") // 5분 주기
public void downLoadBinaryFile() throws Exception {
List<FileVO> files = fileService.selectBinaryFile();
if(files !=null){
for(FileVO vo : files){
File target = FileUtil.getFileDupChk(new File(downloadPath), vo.getFileName());
if(!StringUtils.isEmpty(vo.getFileDataInfo())){
try(OutputStream os = new FileOutputStream(target)){
//vo 의 String -> binary
StreamUtils.copy(vo.getFileDataInfo(),StandardCharsets.UTF_8, os);
log.info("다운로드 완료"+target.getAbsolutePath()); //
} catch (Exception e) {
e.printStackTrace();
log.info("다운로드 실패"+ vo.getFileName());
// TODO: handle exception
}
}
}
}
}