Apache POI 는 MS office 문서포맷을 Java 로 사용할 수 있는 API 를 제공한다.
보통 WorkBook 으로 문서를 만드는 예제나, 암호화된 문서의 암호를 삭제시킬 수 있는 예제들이 떠돌고 있다.
MultipartFile 로 엑셀파일 전달 받고, 해당 파일에 암호 설정해서 돌려주는 API 를 만들어 봤다.
Gradle
dependencies {
implementation 'org.apache.poi:poi:5.2.2'
implementation 'org.apache.poi:poi-ooxml:5.2.2'
}
Java
@PostMapping("/excel/encrypt")
public ResponseEntity<ByteArrayResource> excelEncrypt(@RequestParam MultipartFile file) {
String[] extensionArr = {"xls", "xlsx"}; // 97~, 2007~
String[] mimeTypeArr = {"application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"};
// 파일검증 생략
// apache poi 엑셀 암호화
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (POIFSFileSystem fs = new POIFSFileSystem()) {
EncryptionInfo encryptionInfo = new EncryptionInfo(EncryptionMode.agile);
Encryptor encryptor = encryptionInfo.getEncryptor();
encryptor.confirmPassword("password!@#$");
try (OPCPackage opc = OPCPackage.open(file.getInputStream());
OutputStream outputStream = encryptor.getDataStream(fs)) {
opc.save(outputStream);
}
fs.writeFilesystem(byteArrayOutputStream);
byteArrayOutputStream.close();
} catch (Exception e) {
logger.info(e.getMessage());
}
HttpHeaders header = new HttpHeaders();
String encFileName = URLEncoder.encode(file.getOriginalFilename(), StandardCharsets.UTF_8).replace("+", "%20");
header.setContentType(MediaType.parseMediaType(file.getContentType())); // <- 지정하지 않아도 무관
header.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=utf-8''enc_" + encFileName);
return new ResponseEntity<>(new ByteArrayResource(byteArrayOutputStream.toByteArray()),
header, HttpStatus.OK);
}
POIFS (Poor Obfuscation Implementation File System)
- MS Office 의 OLE 2 Compound document 파일 포맷을 읽고 쓰는 컴포넌트.
- 모든 오피스 파일 포맷은 OLE2 방식이므로 하위 모든 컴포넌트의 기반이 된다.
HSSF (Horrible SpreadSheet Format)
- MS excel 97 이후로 현재까지의 엑셀파일들에 읽고 쓰기를 지원하는 컴포넌트.
XSSF (XML SpreadSheet Format)
- MS excel 2007 이후의 오픈 XML 파일 포맷인 *.xlsx 파일을 읽고 쓰는 컴포넌트.
음~ 잘된당~
용량을 10M 정도 넘겨봤더니, 에러 발생. 늘려보려 했는데... 실패!
Tried to allocate an array of length 132,636,469, but the maximum length for this record type is 100,000,000.
If the file is not corrupt or large, please open an issue on bugzilla to request
increasing the maximum allowable size for this record type.
As a temporary workaround, consider setting a higher override value with IOUtils.setByteArrayMaxOverride()
WRITTEN BY
- 손가락귀신
정신 못차리면, 벌 받는다.