在 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 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 ofiles
.
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 ofiles
.
如果文件都在webapp之外,并且你想让Tomcat的DefaultServlet
来处理它们,那么你在Tomcat中基本上需要做的就是在
标签内的 >/conf/server.xml:
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/files/...
访问.对于基于 Tomcat 的服务器,例如 JBoss EAP 6.x 或更早版本,方法基本相同,另见 这里.GlassFish/Payara 配置示例可以在此处和WildFly 配置示例可以在这里找到.
This way they'll be accessible through http://example.com/files/...
. For Tomcat-based servers such as JBoss EAP 6.x or older, the approach is basically the same, see also here. 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
标头设置为 attachment
,否则客户端将尝试内联显示它.最后只是将文件内容写入响应输出流.
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());
}
}
当映射到例如 /files/*
的 url-pattern
时,您可以通过 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.
您可以重复使用相同的逻辑来提供数据库中的文件.只需将 new FileInputStream()
替换为 ResultSet#getInputStream()
.
You can reuse the same logic for serving files from database. Simply replace new FileInputStream()
by ResultSet#getInputStream()
.
希望这会有所帮助.
- 在 servlet 中保存上传文件的推荐方式申请
- 静态资源servlet的抽象模板(支持HTTP缓存)
- 如何检索并在 JSP 页面中显示来自数据库的图像?
- 如何使用 Servlet 流式传输 MP3、MP4、AVI 等音频/视频文件
- 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屋!