Вопрос-ответ

Simplest way to serve static data from outside the application server in a Java web application

Простейший способ обслуживания статических данных извне сервера приложений в веб-приложении Java

У меня есть веб-приложение Java, работающее на Tomcat. Я хочу загрузить статические изображения, которые будут отображаться как в веб-интерфейсе, так и в файлах PDF, сгенерированных приложением. Также новые изображения будут добавлены и сохранены путем загрузки через веб-интерфейс.

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

На данном этапе я бы предпочел не использовать отдельный веб-сервер, такой как Apache, для обслуживания статических данных. Мне также не нравится идея хранения изображений в двоичном формате в базе данных.

Я видел несколько предложений, например, чтобы каталог изображений был символической ссылкой, указывающей на каталог вне веб-контейнера, но будет ли этот подход работать как в средах Windows, так и * nix?

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

Переведено автоматически
Ответ 1

Я видел несколько предложений, например, чтобы каталог изображений был символической ссылкой, указывающей на каталог вне веб-контейнера, но будет ли этот подход работать как в средах Windows, так и * nix?


Если вы придерживаетесь правил пути к файловой системе * nix (т. Е. Используете исключительно косые черты, как в /path/to/files), то он будет работать и в Windows без необходимости возиться с уродливыми File.separator конкатенациями строк. Однако они будут сканироваться только на том же рабочем диске, с которого была вызвана эта команда. Итак, если Tomcat, например, установлен на C:, то /path/to/files фактически будет указывать на C:\path\to\files.

Если все файлы расположены вне веб-приложения, и вы хотите, чтобы Tomcat DefaultServlet обрабатывал их, то все, что вам в принципе нужно сделать в Tomcat, это добавить следующий элемент контекста в тег /conf/server.xml inside <Host>:

<Context docBase="/path/to/files" path="/files" />

Таким образом, они будут доступны через http://example.com/files/.... Для серверов на базе Tomcat, таких как JBoss EAP 6.x или более поздней версии, подход в основном тот же, смотрите также Здесь. Пример конфигурации 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 of /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().

Смотрите также:

Ответ 2

Вы можете сделать это, разместив свои изображения по фиксированному пути (например: /var/images или c:\images), добавив параметр в настройках вашего приложения (представленный в моем примере параметром Settings.class) и загружать их таким образом в HttpServlet вашем:

String filename = Settings.getValue("images.path") + request.getParameter("imageName")
FileInputStream fis = new FileInputStream(filename);

int b = 0;
while ((b = fis.read()) != -1) {
response.getOutputStream().write(b);
}

Или если вы хотите манипулировать изображением:

String filename = Settings.getValue("images.path") + request.getParameter("imageName")
File imageFile = new File(filename);
BufferedImage image = ImageIO.read(imageFile);
ImageIO.write(image, "image/png", response.getOutputStream());

тогда HTML-код был бы <img src="imageServlet?imageName=myimage.png" />

Конечно, вам следует подумать об обслуживании различных типов контента - "изображение / jpeg", например, на основе расширения файла. Также вам следует обеспечить некоторое кэширование.

Кроме того, вы могли бы использовать этот сервлет для качественного изменения масштаба ваших изображений, предоставляя параметры ширины и высоты в качестве аргументов и используя image.getScaledInstance(w, h, Image.SCALE_SMOOTH), учитывая производительность, конечно.

Ответ 3

Требование: доступ к статическим ресурсам (изображениям / видео и т.д.) Извне каталога WEBROOT или с локального диска

Шаг 1 :
Создайте папку в webapps сервера tomcat., допустим, имя папки - myproj

Шаг 2:
В myproj создайте папку WEB-INF в рамках этого создайте простой web.xml

код в разделе web.xml

<web-app>
</web-app>

Структура каталогов для двух вышеуказанных шагов

c:\programfile\apachesoftwarefoundation\tomcat\...\webapps
|
|---myproj
| |
| |---WEB-INF
| |
|---web.xml

Шаг 3:

Теперь создайте XML-файл с именем myproj.xml в следующем расположении

c:\programfile\apachesoftwarefoundation\tomcat\conf\catalina\localhost

КОД в myproj.xml:

<Context path="/myproj/images" docBase="e:/myproj/" crossContext="false" debug="0" reloadable="true" privileged="true" /> 

Шаг 4:

4 A) Теперь создайте папку с именем myproj на диске E вашего жесткого диска и создайте новую

назовите папку images и поместите некоторые изображения в папку images (e:myproj\images\)

Предположим, myfoto.jpg находится под e:\myproj\images\myfoto.jpg

4 B) Теперь создайте папку с именем WEB-INF в e:\myproj\WEB-INF и создайте web.xml в папке WEB-INF

Код в web.xml

<web-app>
</web-app>

Step 5:
Now create a .html document with name index.html and place under e:\myproj

CODE under index.html


Welcome to Myproj

The Directory Structure for the above Step 4 and Step 5 is as follows

E:\myproj
|--index.html
|
|--images
| |----myfoto.jpg
|
|--WEB-INF
| |--web.xml

Step 6:
Now start the apache tomcat server

Step 7:
open the browser and type the url as follows

http://localhost:8080/myproj    

затем вы отображаете содержимое, которое предоставляется в index.html

Шаг 8:
Для доступа к изображениям на вашем локальном жестком диске (за пределами webroot)

http://localhost:8080/myproj/images/myfoto.jpg
Ответ 4

Добавить в server.xml :

 <Context docBase="c:/dirtoshare" path="/dir" />

Включить параметр dir file listing в web.xml :

    <init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
2023-11-19 19:53 java tomcat servlets jakarta-ee