요구사항
- 사용자가 Download 받는 File을 Copy 해서 별도 분석 모듈에게 전달해야 함
- 사용자는 File Download 를 받는데 달라지는 점이 없어야 함
- 사용자가 File Download 를 받는데 속도 저하가 없어야 함
구현방법
- HttpServletResponse 를 copy 한다.
- filter chain에 copy한 response를 보내고 flulsh 한다.
- finally 에서 copy 본을 이용하여 File 을 생성한다.
HttpServletResponseCopier responseCopier = new HttpServletResponseCopier((HttpServletResponse) response);
try {
chain.doFilter(request, responseCopier);
responseCopier.flushBuffer();
} finally {
writeNewFile(responseCopier.getCopy());
}
코드를 살펴보면 간단하다 .
ServletOutputStream 을 extends 받아 class를 하나 만들고 ByteArrayOutputStream copy를 둬서 write가 호출될 때 copy에도 같이 쓰도록 한다.
HttpServletResponseWrapper 를 extends 받아 class를 하나 맏들고 똑같이 outputStream과 더불어 copy본을 선언해 두고 getWriter, getOutputStream이 호출될 때 copy본을 만들도록 한다.
Filter 에서는 이 copy본을 이용하여 File을 만드는 것이다.
사용자에게 File이 모두 download 된 후에 File이 만들어지기 때문에 사용자 입장에서 속도 저하는 없다.
public class HttpServletResponseCopier extends HttpServletResponseWrapper {
private ServletOutputStream outputStream;
private PrintWriter writer;
private ServletOutputStreamCopier copier;
public HttpServletResponseCopier(HttpServletResponse response) throws IOException {
super(response);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (writer != null) {
throw new IllegalStateException("getWriter() has already been called on this response.");
}
if (outputStream == null) {
outputStream = getResponse().getOutputStream();
copier = new ServletOutputStreamCopier(outputStream);
}
return copier;
}
@Override
public PrintWriter getWriter() throws IOException {
if (outputStream != null) {
throw new IllegalStateException("getOutputStream() has already been called on this response.");
}
if (writer == null) {
copier = new ServletOutputStreamCopier(getResponse().getOutputStream());
writer = new PrintWriter(new OutputStreamWriter(copier, getResponse().getCharacterEncoding()), true);
}
return writer;
}
@Override
public void flushBuffer() throws IOException {
if (writer != null) {
writer.flush();
} else if (outputStream != null) {
copier.flush();
}
}
public byte[] getCopy() {
if (copier != null) {
return copier.getCopy();
} else {
return new byte[0];
}
}
}
public class ServletOutputStreamCopier extends ServletOutputStream {
private OutputStream outputStream;
private ByteArrayOutputStream copy;
public ServletOutputStreamCopier(OutputStream outputStream) {
this.outputStream = outputStream;
this.copy = new ByteArrayOutputStream(1024);
}
@Override
public void write(int b) throws IOException {
outputStream.write(b);
copy.write(b);
}
public byte[] getCopy() {
return copy.toByteArray();
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {
}
}
이제 복사된 파일을 분석하면 된다.
위 코드에서 생략한 부분은
- 분석이 필요한 부분일 경우에만 file 생성하도록 처리하는 부분
- 동일한 파일이 이전에 복사된 적이 있을 경우 (file hash 비교 처리)에 대한 처리
'IT > JAVA' 카테고리의 다른 글
webclient - bodyToMono 예외 처리 (0) | 2020.11.20 |
---|---|
Synchronized 잘 알고 사용하기 (0) | 2020.11.05 |
Cannot deserialize value of type `java.time.LocalDateTime` from String.... `0000-00-00 00:00:00` 처리 방법 (3) | 2020.06.11 |
Java 13 특징 (feat. Java 10 특징) (0) | 2019.12.20 |
Gson Serialize 시 예외 시키기 (@Expose) (0) | 2019.11.28 |