XSSFWorkbook
는 처리하는 엑셀 파일의 전체 데이터를 메모리에 로드한다.XSSFWorkbook
는 파일의 모든 부분을 메모리에 상주시키는 방식으로 구현되어 있다.XSSFWorkbook
는 많은 수의 임시 객체를 생성할 수 있다.public class AwsS3Service {
private final AmazonS3 amazonS3;
@Value("${cloud.aws.s3.bucket}")
private String bucket;
private static final String EXCEL_URL_PREFIX = "https://s3-bucket-url";
public String uploadExcelToS3(SXSSFWorkbook workbook, String originalFilename) {
String fileName = createFileName(originalFilename);
String excelUrl = EXCEL_URL_PREFIX + fileName;
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
workbook.write(outputStream);
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(outputStream.size());
amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, metadata)
.withCannedAcl(CannedAccessControlList.PublicRead));
return excelUrl;
} catch (IOException e) {
log.error("Error uploading file to S3", e);
throw new RuntimeException("Error uploading file to S3", e);
}
}
}
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
workbook.write(outputStream);
...
}
ByteArrayOutputStream
메모리 버퍼에 저장된다. ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
outputStream.toByteArray()
메서드를 호출하면, outputStream
에 저장된 데이터(엑셀 파일의 내용)가 바이트 배열로 변환된다. 이 바이트 배열은 전체 파일 데이터를 메모리에 보유하게 된다.ByteArrayInputStream
이 초기화되며, 이 스트림은 S3 업로드에 사용된다.S3 Bucket 스트리밍 업로드
public void uploadExcelFileToS3(SXSSFWorkbook workbook, String fileName) throws IOException {
// 파일을 디스크에 임시로 저장합니다.
File tempFile = File.createTempFile("excel", ".xlsx");
workbook.write(new FileOutputStream(tempFile));
// TransferManager를 사용하여 파일을 스트리밍 방식으로 S3에 업로드합니다.
TransferManager transferManager = TransferManagerBuilder.standard()
.withS3Client(amazonS3)
.build();
// S3에 업로드를 시작합니다.
Upload upload = transferManager.upload(bucketName, fileName, tempFile);
// 업로드가 완료될 때까지 기다립니다.
upload.waitForCompletion();
// 임시 파일을 삭제합니다.
tempFile.delete();
}
엑셀 데이터 페이징 기법
public void uploadExcelFileToS3WithPaging(String fileName, List<Data> dataList, int pageSize) throws IOException {
int totalSize = dataList.size();
int pageCount = (int) Math.ceil((double) totalSize / pageSize);
for (int i = 0; i < pageCount; i++) {
int startIndex = i * pageSize;
int endIndex = Math.min(startIndex + pageSize, totalSize);
// 페이지별 데이터를 추출합니다.
List<Data> pageData = dataList.subList(startIndex, endIndex);
// 페이지별 데이터로 엑셀 파일을 생성합니다.
SXSSFWorkbook workbook = createWorkbookForPage(pageData);
// 각 페이지를 S3에 업로드합니다.
String pageFileName = fileName + "_part_" + i + ".xlsx";
uploadExcelFileToS3(workbook, pageFileName); // 위에서 설명한 스트리밍 업로드 메소드 사용
}
}
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump/directory