Java/Spring Boot

Spring boot Controller Zip 압축 해제

요술공주밍키 2023. 1. 25. 17:31

회사 프로젝트를 진행하다가 MultipartFile로 전달받은 Zip 파일을 처리하는 방법을 알아보았다.

Spring 게시판도 얼른 마무리 지어야하는데 회사업무 처리하는데 급급하다가

나태지옥에 빠져버려 아직도 손도 못대고 있다... 정신 차려야지 ㅠㅠ

 

Controller

우선 Controller에서 Zip 파일을 받아본다.

@RestController
public class IfElb008Controller {

	@PostMapping("/ifElb008")
	public Map<String, Object> scanImage(@RequestPart MultipartFile files) {
		
		return map;
	}
}

평소와 같이 @RequestBody, @RequestParam을 사용하는 것이 아니라

@RequestPart를 사용하여 MultipartFile을 받아준다.

 

 

Unzip logic

그리고 Controller 안에 압축 해제 로직을 추가해준다.

public static void unzipFile(Path sourceZip, Path targetDir) {
    try (ZipInputStream zis = new ZipInputStream(new FileInputStream(sourceZip.toFile()))) {
        ZipEntry zipEntry = zis.getNextEntry();
        while (zipEntry != null) {
            boolean isDirectory = false;
            if (zipEntry.getName().endsWith(File.separator)) {
                isDirectory = true;
            }
            Path newPath = zipSlipProtect(zipEntry, targetDir);
            if (isDirectory) {
                Files.createDirectories(newPath);
            } else {
                if (newPath.getParent() != null) {
                    if (Files.notExists(newPath.getParent())) {
                        Files.createDirectories(newPath.getParent());
                    }
                }
                Files.copy(zis, newPath, StandardCopyOption.REPLACE_EXISTING);
            }
            zipEntry = zis.getNextEntry();
        }
        zis.closeEntry();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public static Path zipSlipProtect(ZipEntry zipEntry, Path targetDir) throws IOException {
    Path targetDirResolved = targetDir.resolve(zipEntry.getName());
    Path normalizePath = targetDirResolved.normalize();
    if (!normalizePath.startsWith(targetDir)) {
        throw new IOException("Bad zip entry: " + zipEntry.getName());
    }
    return normalizePath;
}

압축을 해제하기 위해서는 로컬 혹은 서버에 다운로드를 받아야 하기 때문에 다운로드 받는

로직 또한 구현해 준다.

 

File download

@Service
public class IfElb008ServiceImpl implements IfElb008Service {
	
	@Override
	public void uploadFile(MultipartFile file) throws IOException {
		file.transferTo(new File("여기에 url" + file.getOriginalFilename()));
	}
}

파일 다운로드는 Service를 따로 만들어서 넣어줬다.

 

최종

@RestController
public class IfElb008Controller {

	@Autowired
	private IfElb008Service ifElb008Service;

	@PostMapping("/ifElb008")
	public Map<String, Object> scanImage(@RequestPart MultipartFile files) {
		try {
            String fileName = url + files.getOriginalFilename();
            // zip 파일 저장 후 압축 해제
            ifElb008Service.uploadFile(files);
            unzipFile(Paths.get(fileName), Paths.get(url));
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 리턴값은 알아서
        return null;
	}
}

이렇게 하면 전달받은 Zip 파일을 저장한 뒤 압축을 해제할 수 있다.