问题
I have a Spring webapp whose .war
file has been uploaded to a Tomcat server. Most of the basic functions are working as intended - page views and form submission.
My problem now is that my webapp needs to read and write files and I am clueless as to how I can achieve this (the file I/O returns java.lang.NullPointerException
).
I used the following code to get the absolute path of a given file suggested by Titi Wangsa Bin Damhore to know the path relative to the server:
HttpSession session = request.getSession();
ServletContext sc = session.getServletContext();
String file = sc.getRealPath("src/test.arff");
logger.info("File path: " + file);
Here is the output path:
/home/username/tomcat/webapps/appname/src/test.arff
But when I checked the file directory via WinSCP, the file's actual path is:
/home/username/tomcat/webapps/appname/WEB-INF/classes/test.arff
Here are my questions:
- How do I transform these paths into something like
C:/Users/Workspace/appname/src/test.arff
(the original path in my local machine that works perfectly)? It's servers areApache Tomcat 6.0.35
andApache Tomcat 6.0.35
. - Why is the code returning a different path as opposed to the actual path?
- If file I/O is not applicable, what alternatives can I use?
PS I just need to access two files (< 1MB each) so I don't think I may need to use a database to contain them as suggested by minus in this thread.
File I/O
Below is the code I use for accessing the file I need.
BufferedWriter writer;
try {
URI uri = new URI("/test.arff");
writer = new BufferedWriter(new FileWriter(
calcModelService.getAbsolutePath() + uri));
writer.write(data.toString());
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
回答1:
To read files:
ServletContext application = ...;
InputStream in = null;
try {
in = application.getResourceAtStream("/WEB-INF/web.xml"); // example
// read your file
} finally {
if(null != in) try { in.close(); }
catch (IOException ioe) { /* log this */ }
}
To write files:
ServletContext application = ...;
File tmpdir = (File)application.getAttribute("javax.servlet.context.tempdir");
if(null == tmpdir)
throw new IllegalStateException("Container does not provide a temp dir"); // Or handle otherwise
File targetFile = new File(tmpDir, "my-temp-filename.txt");
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(targetFile));
// write to output stream
} finally {
if(null != out) try { out.close(); }
catch (IOException ioe) { /* log this */ }
}
If you don't want to use the tmpdir provided by the servlet container, then you should use someplace that is entirely outside of the servlet context's purvue, like /path/to/temporary/files
or something like that. You definitely don't want to use the container's temporary directory for anything other than truly temporary files which are okay to delete on re-deployment, etc.
回答2:
It's a war; you don't read/write files inside it.
Reading is trivial; put the files on the classpath, and read as a resource.
You shouldn't be writing inside a web app anyway, since even if it wasn't a war, things inside the context could disappear during a redeploy, it might only be on one server if you're clustered, etc. File writes should live somewhere configurable.
回答3:
Unless there's some reason you actually need ajava.io.File
, load the file from classpath and don't worry about where it's coming from.
getClass().getClassLoader().getResourceAsStream("test.arff")
回答4:
I used the Spring Resource component to get my file path as suggested by yawn like this (NOTE test.arff
is located in root/src
before war
deployment):
Resource resource = new ClassPathResource("/test.arff");
String arffPathRaw = resource.getURI().toString(); // returns file:/path/to/file
String arffPath = arffPathRaw.replace("file:/", ""); // pure file path
Next, I just concatenated arff
to the files I want like:
URI uri = new URI("test.arff");
BufferedWriter writer = new BufferedWriter(new FileWriter(
arffPath + uri));
I used arffPath
directly in there just for a quick example but I made a function so it will be more convenient.
The file path is actually
/home/username/tomcat/webapps/bosom/WEB-INF/classes/test.arff
so don't be afraid to use this (like I did) just because it doesn't look likeC:/path/to/file
lmaoThose two file paths are the same if used to get a file don't be confused.
来源:https://stackoverflow.com/questions/20403810/tomcat-server-absolute-file-access-in-war-webapp