Java webapp: добавление заголовка Content-disposition для принудительного поведения браузеров "сохранить как"

даже если это не часть HTTP 1.1 / RFC2616 webapps, которые хотят заставить ресурс быть загрузить (не отображается), в браузере можно использовать Content-Disposition заголовок такой:

Content-Disposition: attachment; filename=FILENAME

даже жесткий он определен только в RFC2183 и не часть HTTP 1.1 он работает в большинстве веб-браузеров, как хотел.

Так со стороны клиента, все достаточно хорошо.

однако на стороне сервера, в моем случае, у меня есть Java webapp и я не знаю, как я должен установить этот заголовок, особенно в следующем случае...

у меня будет файл (скажем, называется"bigfile"), размещенную на инстанс Amazon S3 в (мой S3 ведро осуществляется с помощью частичной адрес: files.mycompany.com/) так что пользователи смогут получить доступ к этому файлу на files.mycompany.com/bigfile.

Теперь есть способ создать сервлет (или .jsp) так что Content-Disposition заголовок всегда добавляется, когда пользователь хочет скачать файл?

как будет выглядеть код и что такое gotchas, если таковые имеются?

4 ответов


У вас не было бы URL-адреса, который был бы прямой ссылкой на файл. Вместо этого у вас будет URL-адрес, который приведет к вашему коду сервлета (или к некоторому коду действия в вашей серверной структуре). Это, в свою очередь, должно было бы получить доступ к содержимому файла и выгрузить их клиенту после настройки заголовка. (Вы также хотите помнить, чтобы иметь дело с заголовками управления кэшем, в зависимости от обстоятельств.)

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

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

редактировать я оставлю этот материал здесь для потомства, но я отмечу, что есть (или может быть be) какой-то способ передать некоторые HTTP-заголовки S3, когда вы магазине файл, такой, что Amazon выплюнет их обратно, когда файл будет подан. Я не совсем уверен, как вы это сделаете, и я не уверен, что "Content-disposition" - это заголовок, который вы можете настроить таким образом, но я продолжу искать.


Я получил это работает, как указал острый. Вместо того, чтобы напрямую связываться с активом - в моем случае PDF - файлами-теперь ссылаются на JSP под названием download.jsp, который принимает и анализирует параметры GET, а затем обслуживает pdf в качестве загрузки.

скачать тут

вот код jsp, который я использовал. Его работа в IE8, Chrome и Firefox:

<%@page session="false"
            contentType="text/html; charset=utf-8"
            import="java.io.IOException,
                    java.io.InputStream,
        java.io.OutputStream,
        javax.servlet.ServletContext,
        javax.servlet.http.HttpServlet,
        javax.servlet.http.HttpServletRequest,
        javax.servlet.http.HttpServletResponse,
        java.io.File,
        java.io.FileInputStream"
 %>
<%  
//Set the headers.
response.setContentType("application/x-download"); 
response.setHeader("Content-Disposition", "attachment; filename=downloaded.pdf");

[pull the file path from the request parameters]   

File file = new File("[pdf path pulled from the requests parameters]");
FileInputStream fileIn = new FileInputStream(file);
ServletOutputStream outstream = response.getOutputStream();

byte[] outputByte = new byte[40096];

while(fileIn.read(outputByte, 0, 40096) != -1)
{
    outstream.write(outputByte, 0, 40096);
}
fileIn.close();
outstream.flush();
outstream.close();

%>

поставить .htaccess файл в корневой папке со следующей строкой:

Header set Content-Disposition attachment

Я только что нашел это через google.

и у меня была проблема simmilar, но я все еще хочу использовать сервлет (поскольку я генерирую контент).


следующая строка-это все, что вам нужно в сервлете.
response.setHeader("Content-Disposition", "attachment; filename=downloadedData.json");