Мне нужно отображать изображения, которые находятся за пределами папки развертывания в веб-приложении, используя тег JSF <h:graphicimage> или тег HTML <img>. Как я могу это достичь?
Загружать изображения из папки webapps/webcontext/deploy с помощью тега <h: graphicImage> или <img>
Ответ 1
 Кстати, он должен быть доступен по общедоступному URL. Таким образом, <img src> должен в конечном итоге ссылаться на http:// URI, а не на что-то вроде file:// URI или около того. В конечном счете, исходный код HTML выполняется на компьютере конечного пользователя, и изображения загружаются веб-браузером индивидуально во время анализа исходного кода HTML. Когда веб-браузер обнаруживает URI file:// такой как C:\path\to\image.png, он ищет в файловой системе локального диска конечного пользователя изображение вместо веб-сервера. Это, очевидно, не сработает, если веб-браузер работает на физически другой машине, чем веб-сервер.
Есть несколько способов добиться этого:
-  Если у вас есть полный контроль над папкой с изображениями, просто перетащите папку со всеми изображениями, например, https://stackoverflow.com/imagesнепосредственно в папку развертывания servletcontainer, например, папку/webappsв случае Tomcat и папку/domains/domain1/applicationsв случае GlassFish, Никаких дополнительных настроек не требуется.
-  Или добавьте новый контекст веб-приложения на сервер, который указывает на абсолютное расположение файловой системы диска в папке с этими изображениями. Как это сделать, зависит от используемого контейнера. В приведенных ниже примерах предполагается, что изображения находятся в /path/tohttps://stackoverflow.com/imagesи что вы хотите получить к ним доступ через http://...https://stackoverflow.com/images.В случае Tomcat добавьте следующую новую запись в Tomcat /conf/server.xmlвнутри<Host>:<Context docBase="/path/tohttps://stackoverflow.com/images" path="https://stackoverflow.com/images" />В случае GlassFish добавьте следующую запись в /WEB-INF/glassfish-web.xml:<property name="alternatedocroot_1" value="from=https://stackoverflow.com/images/* dir=/path/to" />В случае WildFly добавьте следующую запись в <host name="default-host">/standalone/configuration/standalone.xml...<location name="https://stackoverflow.com/images" handler="images-content" />... и далее в <handlers>той же<subsystem>что и выше<location>:<file name="images-content" path="/path/tohttps://stackoverflow.com/images" />
-  Или создайте Servletкоторый передает изображение с диска в ответ:@WebServlet("https://stackoverflow.com/images/*") public class ImageServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String filename = request.getPathInfo().substring(1); File file = new File("/path/tohttps://stackoverflow.com/images", filename); response.setHeader("Content-Type", getServletContext().getMimeType(filename)); response.setHeader("Content-Length", String.valueOf(file.length())); response.setHeader("Content-Disposition", "inline; filename=\"" + filename + "\""); Files.copy(file.toPath(), response.getOutputStream()); } }Если вы используете OmniFaces, то FileServletможет быть полезен, так как он также учитывает запросы заголовка, кэширования и диапазона.
-  Или используйте OmniFaces <o:graphicImage>который поддерживает свойство компонента, возвращающееbyte[]илиInputStream:@Named @ApplicationScoped public class Bean { public InputStream getImage(String filename) { return new FileInputStream(new File("/path/tohttps://stackoverflow.com/images", filename)); } }
-  Или используйте PrimeFaces <p:graphicImage>, который поддерживает метод боба возвращающийся PrimeFaces специфичногоStreamedContent.@Named @ApplicationScoped public class Bean { public StreamedContent getImage() throws IOException { FacesContext context = FacesContext.getCurrentInstance(); if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) { // So, we're rendering the view. Return a stub StreamedContent so that it will generate right URL. return new DefaultStreamedContent(); } else { // So, browser is requesting the image. Return a real StreamedContent with the image bytes. String filename = context.getExternalContext().getRequestParameterMap().get("filename"); return new DefaultStreamedContent(new FileInputStream(new File("/path/tohttps://stackoverflow.com/images", filename))); } } }
Для первого способа, а для Tomcat и WildFly - вторым, изображения будут доступны по адресу http://example.comhttps://stackoverflow.com/images/filename.ext и, таким образом, будут ссылаться в обычном HTML следующим образом
<img src="https://stackoverflow.com/images/filename.ext" />
Для подхода GlassFish вторым и третьим способами изображения будут доступны по адресу http://example.com/contexthttps://stackoverflow.com/images/filename.ext и, таким образом, будут ссылаться в обычном HTML следующим образом
<img src="#{request.contextPath}https://stackoverflow.com/images/filename.ext" />
или в JSF следующим образом (автоматически добавляется контекстный путь)
<h:graphicImage value="https://stackoverflow.com/images/filename.ext" />
Для подхода OmniFaces четвертым способом, ссылаться на него следующим образом
<o:graphicImage value="#{bean.getImage('filename.ext')}" />
Для подхода PrimeFaces в пятом способе, ссылаться на него следующим образом:
<p:graphicImage value="#{bean.image}">
    <f:param name="filename" value="filename.ext" />
</p:graphicImage>
 Обратите внимание, что примером #{bean} является @ApplicationScoped поскольку он в основном представляет службу без сохранения состояния. Вы также можете сделать это @RequestScoped, но тогда бин будет воссоздан при каждом отдельном запросе, даром. Вы не можете сделать это @ViewScoped, потому что в настоящее время браузер должен загрузить изображение, сервер не создает страницу JSF. Вы можете сделать это @SessionScoped, но затем он будет сохранен в памяти, даром.
Смотрите также:
- Рекомендуемый способ сохранения загруженных файлов в приложении сервлета
- Самый простой способ обслуживания статических данных извне сервера приложений в веб-приложении Java
- Абстрактный шаблон для сервлета статических ресурсов (с поддержкой HTTP-кэширования)
- Показывать изображение как байт [] из базы данных как графическое изображение на странице JSF
- Отображение динамического изображения из базы данных с помощью p: graphicImage и StreamedContent
- Как правильно выбрать сферу применения бобов?
Ответ 2
Чтобы добиться того, что вам нужно, используя теги <h:graphicImage> или <img>, вам необходимо создать псевдоним Tomcat v7, чтобы сопоставить внешний путь с контекстом вашего веб-приложения.
Для этого вам нужно указать контекст веб-приложения. Самый простой способ - определить файл META-INF/context.xml со следующим содержимым:
<Context path="/myapp" aliases="/images=/path/to/external/images">
</Context>
Затем после перезагрузки сервера Tomcat вы можете получить доступ к своим файлам изображений с помощью тегов <h:graphicImage > или <img> следующим образом:
<h:graphicImage value="/images/my-image.png">
или
<img src="/myapp/images/my-image.png">
* Обратите внимание, что путь для контекста необходим для тега, но не для
Другой возможный подход, если вы не хотите, чтобы изображения были доступны через HTTP GET-метод, может заключаться в использовании Primefaces <p:fileDownload> tag (используя теги commandLink или commandButton - метод HTTP POST).
В вашем Facelet:
<h:form>
  <h:commandLink id="downloadLink" value="Download">  
    <p:fileDownload value="#{fileDownloader.getStream(file.path)}" />  
</h:commandLink>
</h:form
В bean:
@ManagedBean
@ApplicationScope
public class FileDownloader {
    public StreamedContent getStream(String absPath) throws Exception {
        FileInputStream fis = new FileInputStream(absPath);
        BufferedInputStream bis = new BufferedInputStream(fis);
        StreamedContent content = new DefaultStreamedContent(bis);
        return content;
       }
    }
}
Ответ 3
В PrimeFaces вы можете реализовать свой компонент следующим образом:
private StreamedContent image;
public void setImage(StreamedContent image) {
    this.image = image;
}
public StreamedContent getImage() throws Exception {
    return image;
}
public void prepImage() throws Exception {
File file = new File("/path/to/your/image.png");
InputStream input = new FileInputStream(file);
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
setImage(new DefaultStreamedContent(input,externalContext.getMimeType(file.getName()), file.getName()));
}
В вашем HTML Facelet:
<body onload="#{yourBean.prepImage()}"></body> 
<p:graphicImage value="#{youyBean.image}" style="width:100%;height:100%" cache="false" >
</p:graphicImage>
Я предлагаю установить атрибут cache = "false" в компоненте graphicImage.
Ответ 4
В JSP
<img src="data:image/jpeg;base64,
<%= new String(Base64.encode(Files.readAllBytes(Paths.get("C:\\temp\\A.jpg"))))%>"/>
Пакеты com.sun.jersey.core.util.Base64, java.nio.file.Paths и java.nio.file.Files.
