스프링제공 파일유틸클래스

최고고·2025년 5월 27일
0

1. org.springframework.util.FileCopyUtils

파일 복사, 바이트 읽기/쓰기 등에 특화된 간단한 유틸

// 파일 → byte[]
byte[] bytes = FileCopyUtils.copyToByteArray(new File("sample.txt"));

// InputStream → byte[]
byte[] bytes2 = FileCopyUtils.copyToByteArray(inputStream);

// byte[] → OutputStream
FileCopyUtils.copy(bytes, outputStream);

2. org.springframework.web.multipart.MultipartFile

업로드된 파일 처리용 인터페이스 (파일명, 크기, 스트림 등 접근 가능)

String fileName = multipartFile.getOriginalFilename();
byte[] content = multipartFile.getBytes();
multipartFile.transferTo(new File("C:/upload/" + fileName));

3. org.springframework.core.io.Resource & ResourceLoader

클래스패스 리소스, 외부파일 리소스 등 통합 접근

@Autowired
ResourceLoader resourceLoader;

Resource resource = resourceLoader.getResource("classpath:static/sample.txt");
InputStream is = resource.getInputStream();

4. org.springframework.util.StreamUtils

Stream ↔ byte[], String 간 변환

String text = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
byte[] bytes = StreamUtils.copyToByteArray(inputStream);

5. ServletContext.getResourceAsStream() (웹 환경 한정)

InputStream is = servletContext.getResourceAsStream("/WEB-INF/sample.txt");
목적추천 유틸 클래스
파일 복사 / 바이트 I/OFileCopyUtils
업로드 파일 처리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
					}
				
				}
			}
		}
    }

0개의 댓글