IT이야기

브라우저가 파일을 다운로드하도록 강제하는 방법

cyworld 2021. 10. 23. 09:56
반응형

브라우저가 파일을 다운로드하도록 강제하는 방법은 무엇입니까?


모든 것이 잘 작동하지만 파일이 약 1MB인 경우에만 20MB와 같은 더 큰 파일로 시도할 때 강제로 다운로드하는 대신 브라우저에 표시됩니다. 지금까지 많은 헤더를 시도했지만 이제 코드는 다음과 같습니다.

PrintWriter out = response.getWriter();
String fileName = request.getParameter("filename");

File f= new File(fileName);

InputStream in = new FileInputStream(f);
BufferedInputStream bin = new BufferedInputStream(in);
DataInputStream din = new DataInputStream(bin);

while(din.available() > 0){
    out.print(din.readLine());
    out.print("\n");
}

response.setContentType("application/force-download");
response.setContentLength((int)f.length());
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName);


in.close();
bin.close();
din.close();

파일 내용을 출력 스트림에 쓴 후 응답 헤더를 설정하고 있습니다. 헤더를 설정하는 것은 응답 수명 주기에서 상당히 늦습니다. 올바른 작업 순서는 먼저 헤더를 설정한 다음 파일의 내용을 서블릿의 출력 스트림에 쓰는 것입니다.

따라서 메서드는 다음과 같이 작성해야 합니다(단순한 표현이므로 컴파일되지 않음).

response.setContentType("application/force-download");
response.setContentLength((int)f.length());
        //response.setContentLength(-1);
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName);
...
...
File f= new File(fileName);

InputStream in = new FileInputStream(f);
BufferedInputStream bin = new BufferedInputStream(in);
DataInputStream din = new DataInputStream(bin);

while(din.available() > 0){
    out.print(din.readLine());
    out.print("\n");
}

실패의 이유는 서블릿에서 보낸 실제 헤더가 보내려는 것과 다를 수 있기 때문입니다. 결국, 서블릿 컨테이너가 어떤 헤더(HTTP 응답에서 본문 앞에 나타나는지)를 모르는 경우 응답이 유효한지 확인하기 위해 적절한 헤더를 설정할 수 있습니다. 따라서 파일이 작성된 후 헤더를 설정하는 것은 컨테이너가 이미 헤더를 설정했을 수 있으므로 무익하고 중복됩니다. Wireshark 또는 Fiddler 또는 WebScarab과 같은 HTTP 디버깅 프록시를 사용하여 네트워크 트래픽을 보면 이를 확인할 수 있습니다.

이 동작을 이해하려면 ServletResponse.setContentType 에 대한 Java EE API 문서를 참조할 수도 있습니다.

Sets the content type of the response being sent to the client, if the response has not been committed yet. The given content type may include a character encoding specification, for example, text/html;charset=UTF-8. The response's character encoding is only set from the given content type if this method is called before getWriter is called.

This method may be called repeatedly to change content type and character encoding. This method has no effect if called after the response has been committed.

...


Set content-type and other headers before you write the file out. For small files the content is buffered, and the browser gets the headers first. For big ones the data come first.


This is from a php script which solves the problem perfectly with every browser I've tested (FF since 3.5, IE8+, Chrome)

header("Content-Disposition: attachment; filename=\"".$fname_local."\"");
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($fname));

So as far as I can see, you're doing everything correctly. Have you checked your browser settings?

ReferenceURL : https://stackoverflow.com/questions/6520231/how-to-force-browser-to-download-file

반응형