在Java Web应用程序中从应用程序服务器外部提供静态数据的最简单方法 [英] Simplest way to serve static data from outside the application server in a Java web application
问题描述
我有一个在Tomcat上运行的Java Web应用程序。我想加载静态图像,这些图像将在Web UI和应用程序生成的PDF文件中显示。此外,还将通过Web UI上传添加和保存新图像。
I have a Java web application running on Tomcat. I want to load static images that will be shown both on the Web UI and in PDF files generated by the application. Also new images will be added and saved by uploading via the Web UI.
通过将静态数据存储在Web容器中但存储来执行此操作不是问题从Web容器外部加载它们让我很头疼。
It's not a problem to do this by having the static data stored within the the web container but storing and loading them from outside the web container is giving me headache.
我不想在此时使用像Apache这样的单独Web服务器来提供静态数据。我也不喜欢在二进制数据库中存储图像的想法。
I'd prefer not to use a separate web server like Apache for serving the static data at this point. I also don't like the idea of storing the images in binary in a database.
我见过一些建议,比如将图像目录作为指向Web容器外部目录的符号链接,但这种方法在Windows和* nix上都能正常工作环境?
I've seen some suggestions like having the image directory being a symbolic link pointing to a directory outside the web container, but will this approach work both on Windows and *nix environments?
有人建议编写一个过滤器或servlet来处理图像服务,但这些建议非常模糊和高级别,没有指向如何实现这一点的更详细信息。
Some suggest writing a filter or a servlet for handling the image serving but those suggestions have been very vague and high-level without pointers to more detailed information on how to accomplish this.
推荐答案
我看过一些建议,比如将图像目录作为符号链接指向Web容器外的目录,但这种方法是否适用于Windows和* nix环境?
如果你遵守* nix文件系统路径规则(即你在 / path / to / files
中使用专有的正斜杠),那么它也适用于Windows而不需要用丑陋的 File.separator
字符串连接来解决问题。但是,它只能在与调用此命令的位置相同的工作磁盘上进行扫描。因此,如果Tomcat例如安装在 C:
上,那么 / path / to / files
实际上会指向 C:\ path\to\files
。
If you adhere the *nix filesystem path rules (i.e. you use exclusively forward slashes as in /path/to/files
), then it will work on Windows as well without the need to fiddle around with ugly File.separator
string-concatenations. It would however only be scanned on the same working disk as from where this command is been invoked. So if Tomcat is for example installed on C:
then the /path/to/files
would actually point to C:\path\to\files
.
如果这些文件都位于webapp之外,那么你想要使用Tomcat的 DefaultServlet
来处理它们,那么你在Tomcat中基本上需要做的就是将以下Context元素添加到 / conf / server。 xml
在< Host>
标签内:
If the files are all located outside the webapp, and you want to have Tomcat's DefaultServlet
to handle them, then all you basically need to do in Tomcat is to add the following Context element to /conf/server.xml
inside <Host>
tag:
<Context docBase="/path/to/files" path="/files" />
这样他们就可以通过 http://example.com访问/文件/...
。 GlassFish / Payara配置示例可以在此处找到,可以在此处找到WildFly配置示例/ a>。
This way they'll be accessible through http://example.com/files/...
. GlassFish/Payara configuration example can be found here and WildFly configuration example can be found here.
如果你想自己控制读/写文件,那么你需要创建一个 Servlet
为此,它基本上只获得了一个 InputStream
的文件,例如 FileInputStream
,并将其写入
。 HttpServletResponse
的OutputStream
If you want to have control over reading/writing files yourself, then you need to create a Servlet
for this which basically just gets an InputStream
of the file in flavor of for example FileInputStream
and writes it to the OutputStream
of the HttpServletResponse
.
在回复中,您应该设置 Content-Type
标头,以便客户端知道与提供的文件关联的应用程序。并且,您应该设置 Content-Length
标头,以便客户端可以计算下载进度,否则将是未知的。并且,如果您想要另存为 Content-Disposition 标头设置为附件
>对话框,否则客户端将尝试内联显示它。最后只需将文件内容写入响应输出流。
On the response, you should set the Content-Type
header so that the client knows which application to associate with the provided file. And, you should set the Content-Length
header so that the client can calculate the download progress, otherwise it will be unknown. And, you should set the Content-Disposition
header to attachment
if you want a Save As dialog, otherwise the client will attempt to display it inline. Finally just write the file content to the response output stream.
以下是此类servlet的基本示例:
Here's a basic example of such a servlet:
@WebServlet("/files/*")
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String filename = URLDecoder.decode(request.getPathInfo().substring(1), "UTF-8");
File file = new File("/path/to/files", filename);
response.setHeader("Content-Type", getServletContext().getMimeType(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}
映射到<$ c时$ c> url-pattern 例如 / files / *
,然后你可以通过 http://来调用它example.com/files/image.png
。通过这种方式,您可以比 DefaultServlet
更多地控制请求,例如提供默认图像(即 if(!file.exists() )file = new File(/ path / to / files,404.gif)
左右)。使用 request.getPathInfo()
也优先于 request.getParameter()
,因为它更符合SEO,否则在另存为期间,IE不会选择正确的文件名。
When mapped on an url-pattern
of for example /files/*
, then you can call it by http://example.com/files/image.png
. This way you can have more control over the requests than the DefaultServlet
does, such as providing a default image (i.e. if (!file.exists()) file = new File("/path/to/files", "404.gif")
or so). Also using the request.getPathInfo()
is preferred above request.getParameter()
because it is more SEO friendly and otherwise IE won't pick the correct filename during Save As.
您可以重复使用相同的逻辑来从数据库中提供文件。只需通过 ResultSet#getInputStream()
替换 new FileInputStream()
。
You can reuse the same logic for serving files from database. Simply replace new FileInputStream()
by ResultSet#getInputStream()
.
希望这会有所帮助。
- 在servlet应用程序中保存上传文件的推荐方法
- 静态资源servlet的抽象模板(支持HTTP缓存)
- 如何从JSP页面中的数据库中检索和显示图像?
- 如何传输音频/视频文件,如MP3,MP4,AVI等使用Servlet
- Recommended way to save uploaded files in a servlet application
- Abstract template for a static resource servlet (supporting HTTP cache)
- How to retrieve and display images from a database in a JSP page?
- How to stream audio/video files such as MP3, MP4, AVI, etc using a Servlet
这篇关于在Java Web应用程序中从应用程序服务器外部提供静态数据的最简单方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!