Подтвердить что ты не робот

Как заставить браузер загружать файл?

Все работает отлично, но только если файл небольшой, около 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();
4b9b3361

Ответ 1

Вы настраиваете заголовки ответов после записи содержимого файла в выходной поток. Это довольно поздно в жизненном цикле ответа для настройки заголовков. Правильная последовательность операций должна состоять в том, чтобы сначала установить заголовки, а затем записать содержимое файла в выходной поток сервлета.

Следовательно, ваш метод должен быть записан следующим образом (это не будет компилироваться, поскольку это простое представление):

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.

Вы также можете обратиться к документации API Java EE для ServletResponse.setContentType, чтобы понять это поведение:

Устанавливает тип содержимого ответа, отправляемого клиенту, , если ответ еще не был зафиксирован. Данный тип содержимого может включать спецификацию кодировки символов, например text/html; кодировка = UTF-8. Кодировка символов ответа устанавливается только из заданного типа содержимого, если этот метод вызывается до вызова getWriter.

Этот метод может вызываться повторно для изменения типа содержимого и кодировки символов. Этот метод не действует, если вызвано после того, как ответ был зафиксирован.

...

Ответ 2

Задайте тип содержимого и другие заголовки до, вы пишете файл. Для небольших файлов содержимое буферизуется, и браузер сначала получает заголовки. Для больших данных первые данные.

Ответ 3

Это от php script, который отлично решает проблему с каждым проверенным мной браузером (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));

Итак, насколько я вижу, вы все делаете правильно. Вы проверили настройки своего браузера?