왜 내 이미지는 훼손되어 나올까?
서블릿과 파일 업로드를 사용하는 자바 개발자라면 업로드한 이미지가 열었을 때 훼손되거나 손상된 것처럼 보이는 짜증나는 문제에 직면했을 수 있습니다. 텍스트 파일은 문제없이 업로드되는 경우가 많기 때문에 특히 혼란스러울 수 있습니다. 이 블로그 포스트에서는 이러한 현상이 발생하는 이유를 살펴보고 문제를 해결하기 위한 명확한 솔루션을 제공합니다.
문제 이해하기
파일 업로드, 특히 이미지 파일 작업 시 이진 데이터를 올바르게 처리하는 것이 중요합니다. 훼손된 출력은 일반적으로 이진 스트림이 제대로 읽히지 않거나 파일에 정확하게 쓰이지 않았음을 나타냅니다. 아래의 코드 조각은 Apache Commons FileUpload를 사용하여 파일을 업로드하는 전형적인 방법을 보여줍니다:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
...
BufferedInputStream stream = new BufferedInputStream(item.openStream());
...
}
이 방법에서는 이미지와 기타 이진 파일이 처리되지만, 데이터가 읽히는 방식이 이미지 파일을 손상시킬 수 있는 문제를 초래할 수 있습니다.
코드 분석하기
문제에 기여하는 코드의 주요 부분은 입력 스트림에서 바이트를 읽는 방법에서 발견됩니다. 관련 코드 스니펫은 다음과 같습니다:
public static byte[] getBytes(InputStream src, int buffsize) throws IOException {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] buff = new byte[buffsize];
while (true) {
int nBytesRead = src.read(buff);
if (nBytesRead < 0) {
break;
}
byteStream.write(buff);
}
...
}
문제 식별하기
- 전체 버퍼 쓰기:
byteStream.write(buff);
라인은 실제로 읽힌 바이트 수와 관계없이 전체 버퍼를 씁니다. 이는 많은 경우nBytesRead
가 버퍼 크기보다 작게 되어, 이전 읽기에서 남은 바이트가 출력에 기록되어 손상이 발생할 수 있기 때문에 문제가 됩니다.
권장 솔루션
이 문제를 고치기 위해서는 ByteArrayOutputStream
에 바이트를 쓰는 방식을 조정해야 합니다. 수정된 코드는 다음과 같아야 합니다:
public static byte[] getBytes(InputStream src, int buffsize) throws IOException {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] buff = new byte[buffsize];
while (true) {
int nBytesRead = src.read(buff);
if (nBytesRead < 0) {
break;
} else {
byteStream.write(buff, 0, nBytesRead); // 읽은 바이트만 쓰기
}
}
...
}
주요 변경 사항
- 조건부 쓰기:
else
절은 실제로 읽힌 바이트만 쓰도록 보장합니다. - 지정된 길이: 이제 쓰기를 할 때 쓸 바이트 수를 지정합니다.
byteStream.write(buff, 0, nBytesRead);
를 사용하여 말이죠.
이러한 변경은 불필요한 오래된 데이터가 작성되는 것을 방지하고 이미지 파일이 손상 없이 보존되도록 보장합니다.
결론
자바 애플리케이션에서 이미지 업로드 문제를 겪고 있다면, 문제의 원인은 대부분 입력 스트림을 처리하는 방식에 있습니다. 바이트 스트림 읽기 및 쓰기 논리를 다듬어 훼손된 이미지로 이어지는 문제를 제거할 수 있습니다.
위의 지침을 따라서 바이트 스트림의 읽기 및 쓰기 방식을 수정하면, 자바 애플리케이션의 파일 업로드로 인한 미래의 두통을 예방할 수 있습니다. 즐거운 코딩 되세요!