Я видел несколько предложений, например, о том, чтобы каталог изображений был символической ссылкой, указывающей на каталог вне веб-контейнера, но будет ли этот подход работать как в средах 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
.
Onответ, вы должны установить заголовок 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()
.
Надеюсь, это поможет.
См. Также: