Jak zmusić przeglądarkę do pobrania pliku?

Wszystko działa dobrze, ale tylko jeśli plik jest mały, około 1MB, gdy próbowałem go z większymi plikami, jak 20MB wyświetla go moja przeglądarka, zamiast wymuszać pobieranie, próbowałem wiele nagłówków do tej pory, teraz mój kod wygląda: {]}

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();
Author: RivieraKid, 2011-06-29

3 answers

Ustawiasz nagłówki odpowiedzi po zapisaniu zawartości pliku do strumienia wyjściowego. Jest to dość późno w cyklu życia odpowiedzi na ustawianie nagłówków. Poprawną sekwencją operacji powinno być najpierw ustawienie Nagłówków, a następnie zapisanie zawartości pliku do strumienia wyjściowego serwletu.

Dlatego Twoja metoda powinna być napisana w następujący sposób (nie będzie kompilowana, ponieważ jest zwykłą reprezentacją):

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");
}

Powodem awarii jest to, że możliwe jest dla rzeczywistych nagłówków wysyłanych przez servlet będzie różnił się od tego, co zamierzasz wysłać. W końcu, jeśli kontener servletu nie wie, jakie nagłówki (które pojawiają się przed treścią w odpowiedzi HTTP), to może ustawić odpowiednie nagłówki, aby upewnić się, że odpowiedź jest prawidłowa; ustawianie nagłówków po zapisaniu pliku jest zatem daremne i zbędne, ponieważ kontener mógł już ustawić nagłówki. Można to potwierdzić, patrząc na ruch sieciowy za pomocą Wireshark lub serwer proxy do debugowania HTTP, taki jak Fiddler lub WebScarab.

Możesz również zapoznać się z dokumentacją API Java EE dla ServletResponse.setContentType aby zrozumieć to zachowanie:

Ustawia typ treści odpowiedzi wysyłanej do klienta, Jeśli odpowiedź nie została jeszcze zatwierdzona. podany typ zawartości może zawierać specyfikację kodowania znaków, na przykład text / html; charset = UTF-8. Kodowanie znaków odpowiedzi jest ustawione tylko z podanego typu content jeżeli ta metoda zostanie wywołana przed wywołaniem getWriter.

Ta metoda może być wywoływana wielokrotnie w celu zmiany typu zawartości i kodowania znaków. ta metoda nie ma wpływu, jeśli zostanie wywołana po zaangażowaniu odpowiedzi.

...

 64
Author: Vineet Reynolds,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-29 12:14:16

Ustaw content-type i inne nagłówki zanim zapiszesz plik. W przypadku małych plików zawartość jest buforowana, a przeglądarka pobiera nagłówki jako pierwsza. Dla dużych dane są najważniejsze.

 4
Author: Vladimir Dyuzhev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-29 12:06:08

Jest to skrypt php, który doskonale rozwiązuje problem z każdą przeglądarką, którą testowałem (FF od 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));
Z tego co widzę, wszystko robisz poprawnie. Sprawdziłeś ustawienia przeglądarki?
 3
Author: f1sh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-29 12:02:28