在 Java Web 应用程序中从应用程序服务器外部提供静态数据的最简单方法 [英] Simplest way to serve static data from outside the application server in a Java web application

查看:17
本文介绍了在 Java Web 应用程序中从应用程序服务器外部提供静态数据的最简单方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在 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 并将其写入HttpServletResponseOutputStream.

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().

希望这会有所帮助.

  • 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆