webentwicklung-frage-antwort-db.com.de

Laden Sie Bilder von außerhalb des Ordners webapps/webcontext/deploy mit dem Tag <h: graphicImage> oder <img>

Ich muss Bilder anzeigen, die sich außerhalb des Bereitstellungsordners in der Webanwendung befinden, und zwar mit dem JSF <h:graphicimage>-Tag oder dem HTML <img>-Tag. Wie kann ich das erreichen?

Um es auf den Punkt zu bringen, muss es über eine öffentliche URL zugänglich sein. Daher muss der <img src> letztendlich einen http://-URI referenzieren, nicht etwa einen file://-URI oder so. Letztendlich wird die HTML-Quelle auf dem Computer des Endbenutzers ausgeführt, und Bilder werden vom Webbrowser während des Parsens der HTML-Quelle einzeln heruntergeladen. Wenn der Webbrowser auf einen file://-URI wie C:\path\to\image.png stößt, sucht er in dem lokalen lokalen Dateisystem des Endbenutzers nach dem Image und nicht nach dem des Webservers. Dies funktioniert offensichtlich nicht, wenn der Webbrowser auf einem anderen Computer als dem Webserver ausgeführt wird.

Es gibt mehrere Möglichkeiten, dies zu erreichen:

  1. Wenn Sie vollständige Kontrolle über den Bilderordner haben, löschen Sie einfach den Ordner mit allen Bildern, z. /images direkt im Bereitstellungsordner von servletcontainer, z. B. /webapps bei Tomcat und /domains/domain1/applications bei GlassFish. Es ist keine weitere Konfiguration erforderlich.


  2. Oder fügen Sie dem Server einen neuen Webapp-Kontext hinzu, der auf den absoluten Speicherort des Dateisystems des Ordners mit diesen Images verweist. Wie das geht, hängt vom verwendeten Container ab. In den folgenden Beispielen wird davon ausgegangen, dass sich Bilder in /path/to/images befinden und Sie über http: //.../images darauf zugreifen möchten.

    Fügen Sie im Fall von Tomcat den folgenden neuen Eintrag zu Tomcat's /conf/server.xml in <Host> hinzu:

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

    Fügen Sie im Fall von GlassFish den folgenden Eintrag zu /WEB-INF/glassfish-web.xml hinzu:

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

    Im Falle von WildFly fügen Sie den folgenden Eintrag in <Host name="default-Host"> von /standalone/configuration/standalone.xml ... ein.

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

    ... und weiter unten in <handlers> Eingabe desselben <subsystem> wie oben <location>:

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

  3. Oder erstellen Sie eine Servlet, die das Image von der Festplatte zur Antwort überträgt:

    @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());
        }
    }
    

    Wenn Sie OmniFaces verwenden, kann die FileServlet nützlich sein, da auch Kopf-, Caching- und Bereichsanforderungen berücksichtigt werden.


  4. Oder verwenden Sie OmniFaces <o:graphicImage> , das eine Bean-Eigenschaft unterstützt, die byte[] oder InputStream zurückgibt:

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

  5. Oder verwenden Sie PrimeFaces <p:graphicImage> , das eine Bean-Methode unterstützt, die PrimeFaces-spezifische StreamedContent zurückgibt.

    @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)));
            }
        }
    }
    

Für den ersten Weg und die Ansätze von Tomcat und WildFly auf zweitem Weg sind die Bilder unter http://example.com/images/filename.ext verfügbar und daher wie folgt in einfachem HTML referenzierbar

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

Für den GlassFish-Ansatz in zweiter und dritter Richtung stehen die Bilder unter http://example.com/context/images/filename.ext zur Verfügung und können daher wie folgt in einfachem HTML referenziert werden

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

oder in JSF wie folgt (Kontextpfad wird automatisch vorangestellt)

<h:graphicImage value="/images/filename.ext" />

Beziehen Sie sich für den OmniFaces-Ansatz auf die vierte Art und Weise wie folgt

<o:graphicImage value="#{bean.getImage('filename.ext')}" />

Verweisen Sie für den PrimeFaces-Ansatz auf die fünfte Art und Weise wie folgt:

<p:graphicImage value="#{bean.image}">
    <f:param name="filename" value="filename.ext" />
</p:graphicImage>

Beachten Sie, dass das Beispiel #{bean}@ApplicationScoped ist, da es im Wesentlichen einen zustandslosen Dienst darstellt. Sie können es auch zu @RequestScoped machen, aber dann wird das Bean bei jeder einzelnen Anfrage umsonst neu erstellt. Sie können es nicht zu @ViewScoped machen, da der Server zum Zeitpunkt, zu dem das Bild heruntergeladen werden muss, keine JSF-Seite erstellt. Sie können es @SessionScoped machen, aber dann wird es für nichts gespeichert.

Siehe auch:

71
BalusC

Um das zu erreichen, was Sie mit <h:graphicImage>- oder <img>-Tags benötigen, müssen Sie einen Tomcat v7-Alias ​​erstellen, um den externen Pfad dem Kontext Ihrer Webanwendung zuzuordnen.

Dazu müssen Sie den Kontext Ihrer Web-App angeben . Am einfachsten wäre es, eine META-INF/context.xml-Datei mit folgendem Inhalt zu definieren:

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

Nach dem Neustart Ihres Tomcat-Servers können Sie mit den <h:graphicImage> - oder <img>-Tags wie folgt auf Ihre Bilddateien zugreifen:

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

oder

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

* Beachten Sie, dass der Kontextpfad für das Tag erforderlich ist, nicht jedoch für das 


Wenn Sie die Bilder nicht über die HTTP-GET-Methode verfügbar machen möchten, können Sie auch Primefaces <p:fileDownload> tag verwenden (mit commandLink oder commandButton tags - HTTP POST Methode).

In Ihrem Facelet:

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

In deiner Bohne:

@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;
       }
    }
}
2
Ghasfarost

In PrimeFaces können Sie Ihre Bean auf folgende Weise implementieren:

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()));
}

In Ihrem HTML-Facelet:

<body onload="#{yourBean.prepImage()}"></body> 
<p:graphicImage value="#{youyBean.image}" style="width:100%;height:100%" cache="false" >
</p:graphicImage>

Ich empfehle, das Attribut cache = "false" in der graphicImage-Komponente festzulegen.

0
Luca Zammataro