LocalTransfer.download 를 스트리밍 복사로 바꾸고, 4096바이트마다 진행 바이트 수를 로그로 남기세요. 힌트: upload 의 버퍼 반복 구조를 그대로 가져와 방향만 바꿉니다.
@Override
public void download(String remoteName, String localPath) throws TransferException {
Path src = root.resolve(remoteName);
Path dst = Paths.get(localPath);
try (InputStream in = Files.newInputStream(src);
OutputStream out = Files.newOutputStream(dst)) {
byte[] buf = new byte[4096];
long total = 0;
int n;
while ((n = in.read(buf)) != -1) {
out.write(buf, 0, n);
total += n;
System.out.println("다운로드 진행: " + total + " bytes");
}
} catch (IOException e) {
throw new TransferException(Kind.IO, "다운로드 실패: " + remoteName, e);
}
}기존 Files.copy 한 줄보다 코드는 늘지만, 진행 상황을 알아야 하는 대용량 다운로드에서는 이 구조가 필요합니다.
pollAndProcess 는 지금 파일명만으로 중복을 판단합니다. 같은 파일명인데 내용이 다르면 오류로 처리하도록 바꿔보세요. 힌트: Set<String> 대신 Map<String,String>(파일명 → SHA-256)을 씁니다.
private static void pollAndProcess(Path incoming, Path processed,
Map<String, String> processedHash) throws IOException {
try (var s = Files.list(incoming)) {
List<Path> markers = s.filter(p -> p.toString().endsWith(".ok")).sorted().toList();
for (Path marker : markers) {
String name = marker.getFileName().toString();
String base = name.substring(0, name.length() - 3);
Path dataFile = incoming.resolve(base);
if (!Files.exists(dataFile)) continue;
String hash = sha256(dataFile);
String prevHash = processedHash.get(base);
if (prevHash != null) {
if (prevHash.equals(hash)) {
System.out.println("건너뜀(동일 파일 재수신): " + base);
} else {
System.out.println("오류(같은 이름, 다른 내용): " + base);
}
continue;
}
Files.move(dataFile, processed.resolve(base));
Files.delete(marker);
processedHash.put(base, hash);
System.out.println("처리 완료 -> processed/" + base);
}
}
}파일명만 보던 기존 방식보다 안전하지만, 매번 해시를 계산하는 비용이 늘어나므로 대용량 파일에는 크기 비교를 먼저 하는 식으로 절충합니다.
Kind 가 CONNECT 또는 IO 면 재시도하고, AUTH·PERMISSION 이면 바로 알림을 보내는 shouldRetry(Kind) 메서드를 작성하세요.
static boolean shouldRetry(FileTransfer.Kind kind) {
return kind == FileTransfer.Kind.CONNECT || kind == FileTransfer.Kind.IO;
}이 판단을 배치 잡의 재시도 루프에 넣으면, 영구적 실패를 붙잡고 무한 반복하는 사고를 막을 수 있습니다.