Запись изображения в ответ сервлета с лучшей производительностью - PullRequest
10 голосов
/ 05 июня 2010

Я пишу изображение в ответ сервлета с лучшей производительностью. Любые советы, практики, опыт?

Ответы [ 3 ]

22 голосов
/ 05 июня 2010

Для лучшей производительности и эффективности не помещайте весь контент в byte[].Каждый byte съедает, да, один байт из памяти Java.Представьте себе 100 одновременно работающих пользователей, которые запрашивают 10 изображений из каждых 100 КБ, это уже 100 МБ памяти Java, израсходованной.

Получите изображение как InputStream из БД, используя ResultSet#getBinaryStream(), оберните его в BufferedInputStreamи запишите его в OutputStream ответа, завернутого в BufferedOutputStream через небольшой буфер byte[].

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

<img src="images/123">

Создайте класс Servlet, который отображается в web.xml на url-pattern из /images/* и реализуйте его метод doGet() следующим образом .:

Long imageId = Long.valueOf(request.getPathInfo().substring(1)); // 123
Image image = imageDAO.find(imageId); // Get Image from DB.
// Image class is just a Javabean with the following properties:
// private String filename;
// private Long length;
// private InputStream content;

response.setHeader("Content-Type", getServletContext().getMimeType(image.getFilename()));
response.setHeader("Content-Length", String.valueOf(image.getLength()));
response.setHeader("Content-Disposition", "inline; filename=\"" + image.getFilename() + "\"");

BufferedInputStream input = null;
BufferedOutputStream output = null;

try {
    input = new BufferedInputStream(image.getContent());
    output = new BufferedOutputStream(response.getOutputStream());
    byte[] buffer = new byte[8192];
    for (int length = 0; (length = input.read(buffer)) > 0) {
        output.write(buffer, 0, length);
    }
} finally {
    if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
    if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}

В ImageDAO#find() вы можете использовать ResultSet#getBinaryStream(), чтобы получить изображение как InputStream из базы данных.

0 голосов
/ 09 июля 2014

Если изображения статичны, помните, что самый быстрый ответ - это тот, который обрабатывается до того, как он попадет к вам.

Вы можете установить httpd Apache перед вашим сервером Tomcat. Вы можете использовать другие варианты кэширования пограничных серверов. В этом направлении есть множество хитростей.

Конечно, это предполагает, что ваше приложение написано так, что URL-адрес эффективно сопоставляется с одним изображением таким образом, который легко кэшируется. Если в вашем приложении этого нет, преимущества достаточно велики, чтобы рассмотреть возможность реструктуризации.

0 голосов
/ 05 июня 2010

вы можете использовать байт типа массива для изображения из сервлета, если он есть в базе данных типа BLOB-объектов.

byte[] image;

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...