32 votes

Java - Chemin relatif d'un fichier dans une application web Java

Je veux lire un fichier à partir d'une application web Java. Je ne veux pas donner le chemin absolu du fichier. Je veux juste mettre le fichier dans un répertoire de mon application web.

Ou

Il peut être placé avec le fichier .war (application web empaquetée).

Quel chemin relatif donner pour le fichier. J'ai essayé ./filename.csv mais ça n'a pas fonctionné.

\========

À jour

\========

Je livrerai un fichier WAR (application web empaquetée) à mon client. Cette application web lira un fichier (disons FichierFourni.csv) qui sera copié sur le serveur par le client. J'ai donc besoin d'un mécanisme (qui fonctionnera indépendamment de savoir si le serveur d'application va ouvrir le WAR ou non) afin que l'application web puisse lire ce fichier.

Note : Je n'utilise pas le FichierFourni.csv dans un servlet... Je l'utilise dans une classe Java simple...

28voto

Thilo Points 108673

Avez-vous vraiment besoin de le charger à partir d'un fichier? Si vous le placez à côté de vos classes (dans WEB-INF / classes), vous pouvez obtenir un InputStream en utilisant le chargeur de classes:

InputStream csv = 
   SomeClassInTheSamePackage.class.getResourceAsStream("filename.csv");

14voto

Mark Renouf Points 13128

Vous pouvez simplement accéder à un chemin de fichier pré-arrangé sur le système. Ceci est préférable car les fichiers ajoutés au répertoire webapp pourraient être perdus ou le webapp pourrait ne pas être décompressé en fonction de la configuration du système.

Dans notre serveur, nous définissons une propriété système définie dans le JVM du serveur d'application qui pointe vers le "répertoire principal" pour les données externes de notre application. Bien entendu, cela nécessite une modification de la configuration du serveur d'application (-DAPP_HOME=... ajouté à JVM_OPTS au démarrage), nous le faisons principalement pour faciliter les tests de code exécuté en dehors du contexte d'un serveur d'application.

Vous pourriez tout aussi bien récupérer un chemin à partir de la configuration du servlet:

    MyAppHome
    /usr/share/myapp

...

Ensuite, récupérez ce chemin et utilisez-le comme chemin de base pour lire le fichier fourni par le client.

public class MyAppConfig implements ServletContextListener {

    // NOTE: les références statiques ne sont pas une bonne idée, montrées ici pour simplification
    static File appHome;
    static File customerDataFile;

    public void contextInitialized(ServletContextEvent e) {

        appHome = new File(e.getServletContext().getInitParameter("MyAppHome"));
        File customerDataFile = new File(appHome, "SuppliedFile.csv");
    }
}

class DataProcessor {
    public void processData() {
        File dataFile = MyAppConfig.customerDataFile;
        // ...
    }
}

Comme je l'ai mentionné, le problème le plus probable que vous rencontrerez est les restrictions de sécurité. Rien ne garantit que les webapps peuvent lire des fichiers au-dessus de leur racine webapp. Mais il existe généralement des méthodes simples pour accorder des exceptions pour des chemins spécifiques à des webapps spécifiques.

Peu importe le code dans lequel vous avez ensuite besoin d'accéder à ce fichier, puisque vous exécutez une application web, vous êtes assuré que ceci est initialisé en premier, et vous pouvez stocker sa valeur quelque part de pratique pour que le reste de votre code puisse y faire référence, comme dans mon exemple ou mieux encore, simplement transmettre le chemin en tant que paramètre au code qui en a besoin.

9voto

Tim Jansen Points 1736

Si vous avez un chemin pour ce fichier sur le serveur web, vous pouvez obtenir le chemin réel dans le système de fichiers du serveur en utilisant ServletContext.getRealPath(). Notez que cela ne garantit pas de fonctionner dans chaque conteneur (car un conteneur n'est pas obligé de décompresser le fichier WAR et stocker le contenu dans le système de fichiers - la plupart le font cependant). Et je suppose que cela ne fonctionnera pas avec les fichiers dans /WEB-INF, car ils n'ont pas de chemin virtuel.

L'alternative serait d'utiliser ServletContext.getResource() qui renvoie une URI. Cette URI peut être une URL 'file:', mais il n'y a aucune garantie pour cela.

3voto

Hendy Irawan Points 4635

De nombreuses applications web Java populaires, y compris Jenkins et Nexus, utilisent ce mécanisme :

  1. Facultativement, vérifiez un servlet context-param / init-param. Cela permet de configurer plusieurs instances d'applications web par conteneur servlet, en utilisant context.xml qui peut être fait en modifiant le WAR ou en modifiant les paramètres du serveur (dans le cas de Tomcat).

  2. Vérifiez une variable d'environnement (en utilisant System.getenv), si elle est définie, utilisez ce dossier comme dossier de données de votre application. Par exemple, Jenkins utilise JENKINS_HOME et Nexus utilise PLEXUS_NEXUS_WORK. Cela permet une configuration flexible sans aucun changement dans le WAR.

  3. Sinon, utilisez un sous-dossier à l'intérieur du dossier personnel de l'utilisateur, par exemple $HOME/.votreapp. En Java, cela ressemblerait à :

    final File appFolder = new File(System.getProperty("user.home"), ".votreapp");

1voto

Daniel Points 11

L'alternative consisterait à utiliser ServletContext.getResource() qui renvoie un URI. Cet URI peut être une URL 'file:', mais il n'y a aucune garantie pour cela.

Vous n'avez pas besoin qu'il s'agisse d'une URL file:... Vous avez juste besoin qu'il s'agisse d'une URL que votre JVM peut lire - et ce sera le cas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X