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 intégrée).
Quel chemin relatif à donner au fichier. J'ai essayé ./filename.csv
mais ça n'a pas marché.
========
Je vais livrer un fichier WAR
(application web packagée) à mon client. Cette application Web lira un fichier (disons SuppliedFile.csv
) qui sera copié sur le serveur par le client. J'ai donc besoin d'un mécanisme (qui fonctionnera que le serveur d'applications décompresse ou non le WAR
) pour que l'application Web puisse lire ce fichier.
Remarque: Je n'utilise pas le SuppliedFile.csv
dans un servlet ... Je l'utilise dans un simple Java class ...
Avez-vous vraiment besoin de le charger à partir d'un fichier? Si vous le placez le long de vos classes (dans WEB-INF/classes), vous pouvez y obtenir un InputStream en utilisant le chargeur de classe:
InputStream csv =
SomeClassInTheSamePackage.class.getResourceAsStream("filename.csv");
Vous pourrez peut-être 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 peuvent être perdus ou la webapp peut ne pas être décompressée selon la configuration du système.
Dans notre serveur, nous définissons une propriété système définie dans la machine virtuelle Java du serveur d'applications qui pointe vers le "répertoire de base" pour les données externes de notre application. Bien sûr, cela nécessite une modification de la configuration de l'App Server (-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 App Server.
Vous pouvez tout aussi facilement récupérer un chemin depuis la configuration de la servlet:
<web-app>
<context-param>
<param-name>MyAppHome</param-name>
<param-value>/usr/share/myapp</param-value>
</context-param>
...
</web-app>
Récupérez ensuite ce chemin et utilisez-le comme chemin de base pour lire le fichier fourni par le client.
public class MyAppConfig implements ServletContextListener {
// NOTE: static references are not a great idea, shown here for simplicity
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 préparer 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 applications Web spécifiques.
Quel que soit le code dans lequel vous devez ensuite accéder à ce fichier, étant donné que vous exécutez dans une application Web, vous avez la garantie que celui-ci est initialisé en premier et peut cacher sa valeur à un endroit pratique pour que le reste de votre code fasse référence, comme dans mon exemple ou mieux encore, passez simplement le chemin en tant que paramètre au code qui en a besoin.
Si vous avez un chemin pour ce fichier sur le serveur Web, vous pouvez obtenir le vrai chemin dans le système de fichiers du serveur en utilisant ServletContext.getRealPath () . Notez qu'il n'est pas garanti de fonctionner dans tous les conteneurs (car un conteneur n'est pas nécessaire pour 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 retourne un URI. Cet URI peut être une URL "file:", mais il n'y a aucune garantie pour cela.
De nombreuses applications Web populaires Java, y compris Jenkins et Nexus , utilisent ce mécanisme:
Facultativement, vérifiez un paramètre de contexte de servlet/init-param . Cela permet de configurer plusieurs instances Webapp par conteneur de servlet, à l'aide de context.xml
ce qui peut être fait en modifiant le WAR ou en changeant les paramètres du serveur (dans le cas de Tomcat).
Vérifiez une variable d'environnement (en utilisant System.getenv ), si elle est définie, utilisez ce dossier comme dossier de données d'application . par exemple. Jenkins utilise JENKINS_HOME
et Nexus utilise PLEXUS_NEXUS_WORK
. Cela permet une configuration flexible sans aucune modification de WAR.
Sinon, utilisez un sous-dossier dans le dossier de départ de l'utilisateur , par ex. $HOME/.yourapp
. En Java ce sera:
final File appFolder = new File(System.getProperty("user.home"), ".yourapp");
L'alternative serait d'utiliser ServletContext.getResource () qui retourne un URI. Cet URI peut être une URL "file:", mais il n'y a aucune garantie pour cela.
Vous n'avez pas besoin que ce soit un fichier: ... URL. Vous avez juste besoin que ce soit une URL que votre machine virtuelle Java puisse lire - et ce le sera.