Загружайте изображения из-за пределов папки webapps / webcontext / deploy, используя тег <h: graphicImage> или <img> - PullRequest
41 голосов
/ 28 декабря 2010

Мне нужно отображать изображения, которые находятся вне папки развертывания в веб-приложении, используя тег JSF <h:graphicimage> или тег HTML <img>.Как мне этого добиться?

Ответы [ 4 ]

72 голосов
/ 28 декабря 2010

Кстати, он должен быть доступен по общедоступному URL. Таким образом, <img src> должен в конечном итоге ссылаться на http:// URI, а не на что-то вроде file:// URI или около того. В конечном счете, исходный код HTML выполняется на компьютере конечного пользователя, а изображения загружаются веб-браузером индивидуально во время анализа исходного кода HTML. Когда веб-браузер обнаруживает file:// URI, такой как C:\path\to\image.png, он будет искать в файловой системе локального диска конечного пользователя изображение, а не в веб-сервере. Это, очевидно, не сработает, если веб-браузер работает на физически другой машине, чем веб-сервер.

Есть несколько способов добиться этого:

  1. Если у вас есть полный контроль над папкой с изображениями, просто перетащите папку со всеми изображениями, например, /images непосредственно в папке развертывания servletcontainer, такой как папка /webapps в случае Tomcat и папка /domains/domain1/applications в случае GlassFish. Дальнейшая настройка не требуется.


  2. Или добавьте новый контекст веб-приложения на сервер, который указывает на абсолютное расположение файловой системы диска в папке с этими изображениями. Как это сделать, зависит от используемого контейнера. В приведенных ниже примерах предполагается, что изображения расположены в /path/to/images, и вы хотите получить к ним доступ через http: //.../images.

    .

    В случае Tomcat добавьте следующую новую запись в /conf/server.xml Tomcat внутри <Host>:

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

    В случае GlassFish добавьте следующую запись в /WEB-INF/glassfish-web.xml:

    <property name="alternatedocroot_1" value="from=/images/* dir=/path/to" />
    

    В случае WildFly добавьте следующую запись в <host name="default-host"> из /standalone/configuration/standalone.xml ...

    <location name="/images" handler="images-content" />
    

    ... и далее в <handlers> запись того же <subsystem>, что и выше <location>:

    <file name="images-content" path="/path/to/images" />
    

  3. Или создайте Servlet, который передает изображение с диска в ответ:

    @WebServlet("/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/to/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 может оказаться полезным, так как он также учитывает запросы заголовка, кэширования и диапазона.


  4. Или используйте OmniFaces <o:graphicImage>, который поддерживает свойство компонента, возвращающее byte[] или InputStream:

    @Named
    @ApplicationScoped
    public class Bean {
    
        public InputStream getImage(String filename) {
            return new FileInputStream(new File("/path/to/images", filename));
        }
    }
    

  5. Или используйте 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/to/images", filename)));
            }
        }
    }
    

Для первого способа, а для Tomcat и WildFly - вторым, изображения будут доступны по http://example.com/images/filename.ext и, следовательно, будут ссылаться в обычном HTML следующим образом

<img src="/images/filename.ext" />

Для подхода GlassFish вторым и третьим способами изображения будут доступны по http://example.com/context/images/filename.ext и, таким образом, будут ссылаться в обычном HTML следующим образом

<img src="#{request.contextPath}/images/filename.ext" />

или в JSF следующим образом (автоматически добавляется контекстный путь)

<h:graphicImage value="/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, но затем он будет сохранен в памяти, даром.

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

2 голосов
/ 30 апреля 2013

Чтобы добиться того, что вам нужно, используя теги <h:graphicImage> или <img>, вам необходимо создать псевдоним Tomcat v7, чтобы сопоставить внешний путь с контекстом вашего веб-приложения.

Для этого, вам нужно будет указать контекст вашего веб-приложения .Проще всего было бы определить файл META-INF / context.xml со следующим содержимым:

<Context path="/myapp" aliases="/images=/path/to/external/images">
</Context>

Затем после перезапуска сервера Tomcat вы можете получить доступ к файлам изображений, используя <h:graphicImage> или * 1011.* теги следующие:

<h:graphicImage value="/images/my-image.png">

или

<img src="/myapp/images/my-image.png">

* Обратите внимание, что контекстный путь необходим для тега, но не для


Другой возможный подходесли вам не требуется, чтобы изображения были доступны через метод HTTP GET, можно использовать тег Primefaces <p:fileDownload> (используя теги commandLink или commandButton - HTTP POST метод ).

В вашем Facelet:

<h:form>
  <h:commandLink id="downloadLink" value="Download">  
    <p:fileDownload value="#{fileDownloader.getStream(file.path)}" />  
</h:commandLink>
</h:form

В вашем бине:

@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;
       }
    }
}
0 голосов
/ 13 июня 2018

В 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.

0 голосов
/ 15 декабря 2014

В 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.

...