response body를 받아보자.
public class ConnectionFactory {
private HttpURLConnection conn;
...
public String getResponseBody() {
try {
InputStream in = conn.getInputStream();
return new String(in.readAllBytes());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
정말 간단하다.. HttpURLConnection에서는 데이터를 InputStream 형식으로밖에 받지 못한다.
위와 같이 작성해주면 html이든 json이든 다 긁어온다.
파일을 받아보자.
public class ConnectionFactory {
private HttpURLConnection conn;
...
public void saveFile(InputStream in, String path, String filename) {
try {
FileOutputStream out = new FileOutputStream(new File(path, filename));
final int BUFFER_SIZE = 4096;
int byteRead;
byte[] buffer = new byte[BUFFER_SIZE];
while ((byteRead = in.read(buffer)) != -1) {
out.write(buffer, 0, byteRead);
}
out.close();
} catch (IOException e) {
throw new RuntimeException("File Write Error", e);
}
}
}
InputStream에서 String으로 변환 해주었던 것 처럼
InputStream에서 OutputStream으로 변환해주고 반복해서 write해주면 file down이 끝난다.
여기서 주의할점은 new File("...") 로 파일을 생성할 때 경로까지 같이 생성해주지 않으므로
만약 필요하다면 new File("...").mkdir(); 메서드로 디렉터리를 만들어준다.
나는 검증 로직을 다음과 같이 짰다.
1. status code가 200인지
2. response body에 원하는 키워드가 삽입되어 있는지
3. 파일을 다운로드 받았을 때 용량이 적정한지
4. 파일을 다운로드 받았을 때 파일 이름이 형식에 맞는지
이렇게 총 4가지를 검증했다.
첫번째 status code가 200인지
int statusCode = conn.getResponseCode(); // 200 이면 OK
두번째. response body에 원하는 키워드가 삽입되어 있는지
String[] targetKeywords = new String[]{"api", "total", "duration"};
String body = factory.getResponseBody();
boolean totalResult = true;
for (String targetKeyword : targetKeywords) {
boolean result = body.contains(targetKeyword);
if (!result) {
log.warn("해당 키워드가 없음, 키워드 = {}", targetKeyword);
}
totalResult = totalResult && result;
}
// totalResult가 true면 OK
키워드를 하나씩 돌면서 body에 포함되어 있는지 확인한다.
세번째. 파일 용량이 적정한지.
파일용량을 불러오는 방법은 여러가지가 있지만. 여기서는 encoding이 chunked로 response에서 파일 크기를 직접 불러올 수 없을때를 가정하고 구해보겠다.
public int saveFileWithFilesize(InputStream in, String path, String filename) {
int fileSize = 0;
try {
FileOutputStream out = new FileOutputStream(new File(path, filename));
final int BUFFER_SIZE = 4096;
int byteRead;
byte[] buffer = new byte[BUFFER_SIZE];
while ((byteRead = in.read(buffer)) != -1) {
out.write(buffer, 0, byteRead);
fileSize += byteRead;
}
out.close();
return fileSize;
} catch (IOException e) {
throw new RuntimeException("File Write Error", e);
}
}
## 우선 transfer-encoding이 chunked로 되어있지 않고, content-length로 파일 크기를 받아올 수 있다면 이 방법을 사용하지 말자.
파일 다운로드에 해당 로직을 추가하면 시간이 1.5배정도 걸린다.
로직은 inputStream에서 100만큼 읽었으면 100만큼 파일을 써주고, fileSize를 100만큼 증가시키는 것이다.
4번째는 파일 이름이 형식에 맞는지이다.