Я видел несколько предложений, например, чтобы каталог изображений был символической ссылкой, указывающей на каталог за пределами веб-контейнера, но будет ли этот подход работать как в среде Windows, так и в среде * nix?
Если вы придерживаетесь правил пути к файловой системе * nix (то есть используете исключительно прямые косые черты, как в /path/to/files
), тогда он будет работать и в Windows без необходимости возиться с уродливыми File.separator
конкатенациями строк. Однако он будет сканироваться только на том же рабочем диске, с которого была вызвана эта команда. Так что, если Tomcat установлен, например, C:
тогда /path/to/files
фактически будет указывать на C:\path\to\files
.
Если все файлы расположены за пределами веб-приложения, и вы хотите, чтобы Tomcat DefaultServlet
обрабатывал их, все, что вам нужно сделать в Tomcat, - это добавить следующий элемент Context во /conf/server.xml
внутренний <Host>
тег:
<Context docBase="/path/to/files" path="/files" />
Таким образом, они будут доступны через http://example.com/files/...
. Пример конфигурации GlassFish / Payara можно найти здесь, а пример конфигурации WildFly - здесь .
Если вы хотите , чтобы иметь контроль над чтением / запись файлов самостоятельно, то вам необходимо создать Servlet
для этого , которое в основном только получает InputStream
из файла в аромате, например , FileInputStream
и записывает его в OutputStream
из HttpServletResponse
.
В ответе вы должны установить Content-Type
заголовок, чтобы клиент знал, какое приложение связать с предоставленным файлом. И вы должны установить Content-Length
заголовок, чтобы клиент мог рассчитать прогресс загрузки, иначе он будет неизвестен. И вы должны установить Content-Disposition
заголовок, attachment
если вы хотите диалоговое окно « Сохранить как », иначе клиент попытается отобразить его встроенным. Наконец, просто запишите содержимое файла в выходной поток ответа.
Вот базовый пример такого сервлета:
@WebServlet("/files/*")
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String filename = URLDecoder.decode(request.getPathInfo().substring(1), "UTF-8");
File file = new File("/path/to/files", filename);
response.setHeader("Content-Type", getServletContext().getMimeType(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}
При отображении, url-pattern
например /files/*
, на из , вы можете вызвать его по http://example.com/files/image.png
. Таким образом, вы можете иметь больший контроль над запросами, чем DefaultServlet
они, например, предоставлять изображение по умолчанию (т.е. if (!file.exists()) file = new File("/path/to/files", "404.gif")
или около того). Также request.getPathInfo()
предпочтительнее использовать выше, request.getParameter()
потому что он более дружественен к SEO, и в противном случае IE не выберет правильное имя файла при сохранении как .
Вы можете повторно использовать ту же логику для обслуживания файлов из базы данных. Просто замените new FileInputStream()
на ResultSet#getInputStream()
.
Надеюсь это поможет.
Смотрите также: