zip을 제공하는 JSP가 파일을 손상시킵니다.
문제
JSP에서 zip 파일을 제공하는 데 문제가 있습니다.
zip 파일은 다운로드가 완료된 후 항상 손상됩니다.나는 읽고 쓰기 위해 몇 가지 다른 방법을 시도했지만 그 중 어느 것도 효과가 없는 것 같습니다.
파일이 열리고 모든 파일 이름이 표시되기 때문에 어딘가에 ASCII 문자를 추가하는 것 같지만 파일을 추출할 수는 없습니다.
내 최신 코드는 다음과 같습니다.
<%@ page import= "java.io.*" %>
<%
BufferedReader bufferedReader = null;
String zipLocation = "C:\\zipfile.zip";
try
{
bufferedReader = new BufferedReader(new FileReader(zipLocation));
response.setContentType("application/zip");
response.setHeader( "Content-Disposition", "attachment; filename=zipfile.zip" );
int anInt = 0;
while((anInt = bufferedReader.read()) != -1)
{
out.write(anInt);
}
}
catch(Exception e)
{
e.printStackTrace();
}
%>
편집하다:코드를 서블릿으로 옮겼는데 여전히 작동하지 않습니다.주변에 더 많은 항목을 변경했으므로 작동하지 않는 최신 코드는 다음과 같습니다.
public void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException
{
try
{
String templateLocation = Config.getInstance().getString("Site.templateDirectory");
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=output.zip;");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(baos);
FileInputStream fis = new FileInputStream(templateLocation);
int len;
byte[] buf = new byte[1024];
while ((len = fis.read(buf)) > 0)
{
bos.write(buf, 0, len);
}
bos.close();
PrintWriter pr = response.getWriter();
pr.write(baos.toString());
pr.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
편집2:
이것이 제가 실제로 작동하는 서블릿 코드입니다.모두에게 감사드립니다!
public void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException
{
try
{
String templateLocation = Config.getInstance().getString("Site.templateDirectory");
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=output.zip;");
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
FileInputStream fis = new FileInputStream(templateLocation);
int len;
byte[] buf = new byte[1024];
while ((len = fis.read(buf)) > 0)
{
bos.write(buf, 0, len);
}
bos.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
해결책
ZIP는 이진 파일이므로 문자 데이터로 전송하기에 적합하지 않습니다. 또한 코드 외부의 텍스트는 파일을 손상시킬 수 있습니다.
JSP 대신 평원 바닐라 서블릿을 사용하십시오.
다른 팁
JSP는 출력에 공백을 추가합니다.이것을 서블릿으로 옮기는 것이 좋습니다.
또는 다음을 살펴볼 수 있습니다. JSP 출력에서 공백 제거 , 그러나 ZIP 출력 자체에는 영향을 미치지 않을지 확실하지 않습니다.
이 정확한 스 니펫의 문제는 2 행에 있습니다. JSP 태그 외부에 빈 줄이있어 브라우저로 HTML로 전송됩니다 (즉, HTML 소스의 빈 줄).
< % %>, 특히 공백 (터미널 뉴 라인)이 아닌 것을 제거하거나 다른 곳에서 조언을 따르고 서블릿을 사용하도록 매우주의하십시오. :)
스트림을 response.getWriter()
, 다른 사람들이 지적한대로 문자 데이터. 나는 Javadoc을 인용합니다.
PrintWriter getWriter() throws IOException
클라이언트에게 문자 텍스트를 보낼 수있는 인쇄기 객체를 반환합니다. Printwriter는 getcharacterencoding ()에 의해 반환 된 문자 인코딩을 사용합니다.
뿐만 아니라 바이트 배열을 Writer
, 당신은 결과를 쓰고 있습니다 ByteArrayOutputStream.toString()
, 캐릭터 변환을 수행합니다 ~
response.getOutputStream ()을 사용하려고합니다.
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
그런 다음 파일의 바이트 내용을 작성하십시오.
내가 올바르게 기억한다면 독자는 일반적으로 캐릭터 스트림을위한 것입니다. 바이트 라우 포트 스트림의 선을 따라 더 많은 것을 시도 할 수 있습니까? 또한 JSP는 다른 사람들이 언급 한 것처럼 실제로 출력을 손상시킬 수 있습니다.
bufferedReader = new BufferedReader(new FileReader(zipLocation));
Servlet/JSP 문제 외에도 이 줄은 100% 확실하게 데이터를 손상시킵니다.기본 플랫폼 인코딩을 사용하여 이진 데이터를 텍스트로 해석하려고 시도합니다. 이는 파일의 약 절반 바이트가 "알 수 없는 문자"로 대체됨을 의미합니다.
바이트와 문자열은 같은 것이 아닙니다!
나는 또한 일반 서블릿을 사용하는 것을 제안하고 Robert Munteanu의 대답 맞습니다. 그러나 당신은 당신의 JSP에서도 이것을 할 수 있습니다. 문제는 추가 된 공백은 아니지만 암시 적 변수 "out"은 JSPWriter의 인스턴스이며 작가는 바이트가 아닌 캐릭터를위한 것입니다. 사용하려고 노력하십시오 Response.getOutputStream () 그리고 바로 그것에 대해서는 작동해야합니다. 다른 사람이 이미 출력 스트림을 받았다는 예외를 얻을 수 있지만 무시할 수 있습니다.
그러나 내가 말했듯이, 서블릿을 사용하는 것은 훨씬 깨끗할 것입니다.