Как заставить браузер загрузить файл?
все работает нормально, но только если файл маленький, около 1 МБ, когда я пробовал его с большими файлами, например 20 МБ мой браузер отображает его, вместо того, чтобы загружать, я пробовал много заголовков до сих пор, теперь мой код выглядит:
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();
3 ответа:
вы устанавливаете заголовки ответов после записи содержимого файла в выходной поток. Это довольно поздно в жизненном цикле ответа, чтобы установить заголовки. Правильная последовательность операций должна состоять в том, чтобы сначала установить заголовки, а затем записать содержимое файла в выходной поток сервлета.
поэтому ваш метод должен быть записан следующим образом (это не будет компилироваться, поскольку это просто представление):
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 или прокси-сервера отладки HTTP, такого как Fiddler или WebScarab.
вы также можете обратиться к документации Java EE API для ServletResponse.setContentType чтобы понять такое поведение:
задает тип содержимого ответа, отправляемого клиенту, если ответ еще не зафиксированы. данный тип контента может включать в себя спецификацию кодировки символов, например, text/html;charset=UTF-8. Этот кодировка символов ответа устанавливается только из данного типа контента, если этот метод вызывается до вызова getWriter.
этот метод может быть вызван несколько раз, чтобы изменить тип контента и кодировку. этот метод не действует, если вызывается после фиксации ответа.
...
установить content-type и другие заголовки до вы записываете файл. Для небольших файлов содержимое буферизуется, и браузер сначала получает заголовки. Для больших данные на первом месте.
Это из php-скрипта, который отлично решает проблему с каждым браузером, который я тестировал (FF с 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));
Так что, насколько я вижу, вы все делаете правильно. Вы проверили настройки Вашего браузера?