Méthode la plus simple pour diffuser des données statiques depuis l’extérieur du serveur d’applications dans une application Web Java

J’ai une application Web Java exécutée sur Tomcat. Je souhaite charger des images statiques qui seront affichées à la fois sur l’interface utilisateur Web et dans les fichiers PDF générés par l’application. De plus, de nouvelles images seront ajoutées et enregistrées en téléchargeant via l’interface Web.

Ce n’est pas un problème de faire cela en ayant les données statiques stockées dans le conteneur Web, mais les stocker et les charger depuis l’extérieur du conteneur Web me donne mal à la tête.

Je préférerais ne pas utiliser un serveur Web distinct comme Apache pour servir les données statiques à ce stade. Je n’aime pas non plus l’idée de stocker les images en binary dans une firebase database.

J’ai vu des suggestions comme avoir le répertoire image comme un lien symbolique pointant vers un répertoire hors du conteneur Web, mais cette approche fonctionnera-t-elle à la fois sur les environnements Windows et * nix?

Certains suggèrent d’écrire un filtre ou un servlet pour gérer l’image en train de servir, mais ces suggestions ont été très vagues et de haut niveau, sans pointeurs vers des informations plus détaillées sur la manière d’y parvenir.

J’ai vu des suggestions comme avoir le répertoire image comme un lien symbolique pointant vers un répertoire hors du conteneur Web, mais cette approche fonctionnera-t-elle à la fois sur les environnements Windows et * nix?

Si vous respectez les règles de chemin du système de fichiers * nix (c.-à-d. Que vous utilisez exclusivement des barres obliques comme /path/to/files ), cela fonctionnera aussi sous Windows sans avoir à File.separator de concaténations de chaînes File.separator . Il ne serait cependant analysé que sur le même disque de travail que celui à partir duquel cette commande a été appelée. Donc, si Tomcat est par exemple installé sur C: alors les /path/to/files pointeraient effectivement sur C:\path\to\files .

Si tous les fichiers sont situés en dehors de l’application Web et que vous souhaitez que DefaultServlet de Tomcat les gère, il vous suffit d’append l’élément Context suivant dans /conf/server.xml dans la :

  

De cette façon, ils seront accessibles via http://example.com/files/... L’exemple de configuration de GlassFish / Payara peut être trouvé ici et l’exemple de configuration de WildFly peut être trouvé ici .

Si vous voulez contrôler vous-même la lecture / écriture de fichiers, vous devez créer un Servlet pour cela, il suffit simplement d’obtenir un InputStream du fichier par exemple FileInputStream et de l’écrire dans OutputStream de HttpServletResponse .

Sur la réponse, vous devez définir l’en Content-Type tête Content-Type pour que le client sache quelle application associer au fichier fourni. Et, vous devez définir l’en Content-Length tête Content-Length afin que le client puisse calculer la progression du téléchargement, sinon il sera inconnu. Et, vous devez définir l’en Content-Disposition tête Content-Disposition sur attachment si vous voulez une boîte de dialog Enregistrer sous , sinon le client tentera de l’afficher en ligne. Enfin, écrivez simplement le contenu du fichier dans le stream de sortie de la réponse.

Voici un exemple élémentaire d’un tel servlet:

 @WebServlet("/files/*") public class FileServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Ssortingng filename = URLDecoder.decode(request.getPathInfo().subssortingng(1), "UTF-8"); File file = new File("/path/to/files", filename); response.setHeader("Content-Type", getServletContext().getMimeType(filename)); response.setHeader("Content-Length", Ssortingng.valueOf(file.length())); response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\""); Files.copy(file.toPath(), response.getOutputStream()); } } 

Lorsque mappé sur un url-pattern d’ url-pattern par exemple /files/* , vous pouvez l’appeler par http://example.com/files/image.png . De cette façon, vous pouvez avoir plus de contrôle sur les requêtes que le DefaultServlet , comme fournir une image par défaut (ie if (!file.exists()) file = new File("/path/to/files", "404.gif") ou alors). L’utilisation de request.getPathInfo() est également préférable à request.getParameter() car il est plus convivial en termes de référencement, sinon IE ne choisira pas le nom de fichier correct lors de l’ enregistrement sous.

Vous pouvez réutiliser la même logique pour servir des fichiers depuis une firebase database. Remplacez simplement le new FileInputStream() par ResultSet#getInputStream() .

J’espère que cela t’aides.

Voir également:

  • Méthode recommandée pour enregistrer les fichiers téléchargés dans une application de servlet
  • Modèle abstrait pour un servlet de ressource statique (prenant en charge le cache HTTP)
  • Comment récupérer et afficher des images d’une firebase database dans une page JSP?
  • Comment diffuser des fichiers audio / vidéo tels que MP3, MP4, AVI, etc. à l’aide d’un servlet

Vous pouvez le faire en plaçant vos images sur un chemin fixe (par exemple: / var / images ou c: \ images), ajoutez un paramètre dans les parameters de votre application (représenté dans mon exemple par Settings.class) et chargez-les. comme ça, dans votre HttpServlet :

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

Ou si vous voulez manipuler l’image:

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

alors le code html serait

Bien sûr, vous devriez penser à servir différents types de contenu – “image / jpeg”, par exemple en fonction de l’extension du fichier. Aussi, vous devriez fournir une mise en cache.

En outre, vous pouvez utiliser ce servlet pour le redimensionnement de la qualité de vos images, en fournissant des parameters de largeur et de hauteur comme arguments et en utilisant image.getScaledInstance(w, h, Image.SCALE_SMOOTH ), en tenant compte des performances, bien sûr.

Condition requirejse: Accéder aux ressources statiques (images / vidéos., Etc.) en dehors du répertoire WEBROOT ou du disque local

Étape 1 :
Créez un dossier sous webapps du serveur tomcat, disons que le nom du dossier est myproj

Étape 2 :
Sous myproj, créez un dossier WEB-INF sous ce créer un simple web.xml

code sous web.xml

   

Structure de répertoire pour les deux étapes ci-dessus

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

Étape 3:
Créez maintenant un fichier xml nommé myproj.xml sous l’emplacement suivant

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

CODE dans myproj.xml:

  

Étape 4:
4 A) Créez maintenant un dossier nommé myproj dans le lecteur E de votre disque dur et créez un nouveau fichier.

dossier avec des images de nom et placer des images dans le dossier images (e:myproj\images\)

Supposons que myfoto.jpg soit placé sous e:\myproj\images\myfoto.jpg

4 B) Maintenant, créez un dossier nommé WEB-INF dans e:\myproj\WEB-INF et créez un fichier web.xml dans le dossier WEB-INF.

Code dans web.xml

   

Étape 5:
Maintenant, créez un document .html avec le nom index.html et placez-le sous e: \ myproj

CODE sous index.html Bienvenue dans Myproj

La structure de répertoire pour les étapes 4 et 5 ci-dessus est la suivante

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

Étape 6:
Maintenant, démarrez le serveur apache tomcat

Étape 7:
Ouvrez le navigateur et tapez l’URL comme suit

 http://localhost:8080/myproj 

puis affichez le contenu fourni dans index.html

Étape 8:
Pour accéder aux images sous votre disque dur local (en dehors de webroot)

 http://localhost:8080/myproj/images/myfoto.jpg 

Ajoutez à server.xml:

   

Activer le paramètre de liste de fichiers dir dans web.xml:

   listings true  

C’est l’histoire de mon lieu de travail:
– Nous essayons de télécharger des images multiples et les fichiers de documents utilisent Struts 1 et Tomcat 7.x.
– Nous essayons d’écrire les fichiers téléchargés sur le système de fichiers, le nom de fichier et le chemin complet des enregistrements de la firebase database.
– Nous essayons de séparer les dossiers de fichiers en dehors du répertoire des applications Web . (*)

La solution ci-dessous est assez simple, efficace pour l’exigence (*):

Dans le fichier META-INF/context.xml avec le contenu suivant: (Exemple, mon application s’exécute à http://localhost:8080/ABC , mon application / projet nommé ABC ). (c’est aussi le contenu complet du fichier context.xml )

   

(fonctionne avec Tomcat version 7 ou ultérieure)

Résultat: nous avons été créés 2 alias. Par exemple, nous enregistrons des images sur: D:\images\foo.jpg et visualisons depuis un lien ou en utilisant une balise image:

 Foo 

ou

 Foo 

(J’utilise Netbeans 7.x, les Netbeans semblent créer automatiquement le fichier WEB-INF\context.xml )

Si vous décidez d’envoyer à FileServlet vous aurez également besoin de allowLinking="true" dans context.xml pour permettre à FileServlet de parcourir les liens symboliques.

Voir http://tomcat.apache.org/tomcat-6.0-doc/config/context.html

Si quelqu’un n’est pas en mesure de résoudre son problème avec une réponse acceptée, notez ces considérations ci-dessous:

  1. pas besoin de mentionner localhost: avec l’atsortingbut src .
  2. assurez-vous que vous exécutez ce projet en dehors d’eclipse, car eclipse crée context docBase entrée context docBase dans son propre fichier server.xml .

Lisez le InputStream d’un fichier et écrivez-le sur ServletOutputStream pour envoyer des données binarys au client.

  • Fichier local Vous pouvez lire un fichier directement à l’aide de FileInputStream (‘path / image.png’) .
  • Fichier Mongo DataBase, vous pouvez obtenir InputStream en utilisant GridFS .
 @WebServlet("/files/URLStream") public class URLStream extends HttpServlet { private static final long serialVersionUID = 1L; public URLStream() { super(); } protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { File source = new File("D:\\SVN_Commit.PNG"); long start = System.nanoTime(); InputStream image = new FileInputStream(source); /*Ssortingng fileID = request.getParameter("id"); System.out.println("Requested File ID : "+fileID); // Mongo DB GridFS - https://stackoverflow.com/a/33544285/5081877 image = outputImageFile.getInputStream();*/ if( image != null ) { BufferedInputStream bin = null; BufferedOutputStream bout = null; ServletOutputStream sos = response.getOutputStream(); try { bin = new BufferedInputStream( image ); bout = new BufferedOutputStream( sos ); int ch =0; ; while((ch=bin.read())!=-1) { bout.write(ch); } } finally { bin.close(); image.close(); bout.close(); sos.close(); } } else { PrintWriter writer = response.getWriter(); writer.append("Something went wrong with your request."); System.out.println("Image not available."); } System.out.println("Time taken by Stream Copy = "+(System.nanoTime()-start)); } } 

Résultat l’URL directement à l’atsortingbut src .

 mongodb File local file  

Si vous voulez travailler avec JAX-RS (par exemple, RESTEasy), essayez ceci:

 @Path("/pic") public Response get(@QueryParam("url") final Ssortingng url) { Ssortingng picUrl = URLDecoder.decode(url, "UTF-8"); return Response.ok(sendPicAsStream(picUrl)) .header(HttpHeaders.CONTENT_TYPE, "image/jpg") .build(); } private StreamingOutput sendPicAsStream(Ssortingng picUrl) { return output -> { try (InputStream is = (new URL(picUrl)).openStream()) { ByteStreams.copy(is, output); } }; } 

en utilisant javax.ws.rs.core.Response et com.google.common.io.ByteStreams

Je l’ai fait encore plus simple. Problème: Un fichier CSS comportait des liens vers le dossier img. Obtient 404.

J’ai regardé l’url, http: // tomcatfolder: port / img / blablah.png , qui n’existe pas. Mais, cela pointe vraiment vers l’application ROOT dans Tomcat.

Je viens donc de copier le dossier img de mon application Web dans cette application ROOT. Travaux!

Ce n’est pas recommandé pour la production, bien sûr, mais c’est pour une application de développement d’outil interne.