Java war webapp中Tomcat服务器绝对文件访问
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20403810/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Tomcat server absolute file access in war webapp
提问by
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.
我有一个 Spring webapp,其.war
文件已上传到 Tomcat 服务器。大多数基本功能都按预期工作 - 页面查看和表单提交。
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
).
我现在的问题是我的 webapp 需要读取和写入文件,我对如何实现这一点一无所知(文件 I/O 返回java.lang.NullPointerException
)。
I used the following code to get the absolute path of a given filesuggested by Titi Wangsa Bin Damhoreto know the path relative to the server:
我使用以下代码获取Titi Wangsa Bin Damhore建议的给定文件的绝对路径,以了解相对于服务器的路径:
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:
但是当我通过WinSCP检查文件目录时,文件的实际路径是:
/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?
- 我如何将这些路径转换为类似
C:/Users/Workspace/appname/src/test.arff
(本地机器中完美运行的原始路径)?它的服务器是Apache Tomcat 6.0.35
和Apache Tomcat 6.0.35
。 - 为什么代码返回的路径与实际路径不同?
- 如果文件 I/O 不适用,我可以使用哪些替代方法?
PSI 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 minusin this thread.
PS我只需要访问两个文件(<1MB的每个),所以我不认为我可能需要使用数据库中包含他们所建议减去在此线程。
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();
}
采纳答案by Christopher Schultz
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.
如果您不想使用 servlet 容器提供的 tmpdir,那么您应该使用一个完全在 servlet 上下文的权限之外的地方,例如/path/to/temporary/files
或类似的东西。您绝对不想将容器的临时目录用于除真正的临时文件之外的任何内容,这些文件可以在重新部署时删除等。
回答by Dave Newton
It's a WAR. You don't read/write files inside it.
这是一场战争。您不会在其中读取/写入文件。
Reading is trivial: put the files on the classpath, and then read as a resource.
读取很简单:将文件放在类路径上,然后作为资源读取。
You shouldn't be writing inside a web app anyway since, even if it wasn'ta WAR, things inside the context could disappear during a redeploy, or it might only be on one server if you're clustered, etc. Instead file writes should live somewhere configurable.
无论如何,您不应该在 Web 应用程序中编写代码,因为即使它不是WAR,上下文中的内容也可能在重新部署期间消失,或者如果您是集群的,则它可能只在一台服务器上,等等。而是文件写入应该存在于可配置的地方。
回答by Chris Martin
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.
除非出于某种原因,您确实需要java.io.File
从类路径加载文件,并且不要担心它来自哪里。
getClass().getClassLoader().getResourceAsStream("test.arff")
回答by Chris Martin
I used the Spring Resource
component to get my file pathas suggested by yawnlike this (NOTEtest.arff
is located in root/src
before war
deployment):
我使用SpringResource
组件来获取我的文件路径,如yawn所建议的那样(注意test.arff
位于部署root/src
之前war
):
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:
接下来,我只是连接arff
到我想要的文件:
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.
我arffPath
直接在那里使用只是为了一个简单的例子,但我做了一个函数,所以它会更方便。
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.
文件路径实际上是
/home/username/tomcat/webapps/bosom/WEB-INF/classes/test.arff
这样的,所以不要害怕使用它(就像我一样)只是因为它看起来不像C:/path/to/file
lmao如果用于获取文件,请不要混淆这两个文件路径。