一尘不染

在Java Web应用程序中从应用程序服务器外部提供静态数据的最简单方法

tomcat

我有一个在Tomcat上运行的Java Web应用程序。我想加载静态图像,这些图像将同时显示在Web UI和应用程序生成的PDF文件中。通过Web
UI上载还将添加和保存新图像。

通过将静态数据存储在Web容器中来执行此操作不是问题,但是从Web容器外部存储和加载静态数据让我头疼。

我现在不希望使用像Apache这样的单独的Web服务器来提供静态数据。我也不喜欢将图像以二进制形式存储在数据库中的想法。

我已经看到了一些建议,例如将图像目录作为指向Web容器外部目录的符号链接,但是这种方法在Windows和* nix环境下都可以使用吗?

有些人建议编写一个用于处理图像服务的过滤器或Servlet,但是这些建议非常模糊且笼统,没有指向如何实现此目的的更详细信息的指针。


阅读 284

收藏
2020-06-16

共1个答案

一尘不染

我已经看到了一些建议,例如将图像目录作为指向Web容器外部目录的符号链接,但是这种方法在Windows和* nix环境下都可以使用吗?

如果您遵循*
nix文件系统路径规则(即,您仅使用中的正斜杠/path/to/files),那么它也将在Windows上运行,而无需摆弄丑陋的File.separator字符串连接。但是,只能在与调用该命令的位置相同的工作磁盘上对其进行扫描。因此,例如如果安装了Tomcat,C:/path/to/files实际指向C:\path\to\files

如果这些文件都位于webapp之外,并且您想让Tomcat
DefaultServlet处理这些文件,那么在Tomcat中,您基本上要做的就是将以下Context元素添加到/conf/server.xmlinside
<Host>标记中:

<Context docBase="/path/to/files" path="/files" />

这样,就可以通过访问它们http://example.com/files/...。GlassFish /
Payara配置示例如果您想自己控制文件的读写,那么您需要为此创建一个Servlet,它基本上只是InputStream以例如的形式获取文件的FileInputStream并将其写入的OutputStreamHttpServletResponse

在响应上,您应该设置Content-Type标题,以便客户端知道要与提供的文件关联的应用程序。并且,您应该设置Content- Length标题,以便客户端可以计算下载进度,否则它将是未知的。并且,如果需要“ 另存为” 对话框,则应将Content- Disposition标题设置为,否则客户端将尝试内联显示它。最后,只需将文件内容写入响应输出流即可。attachment __

这是这种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());
    }

}

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在“
另存为” 期间将不会选择正确的文件名。

您可以重复使用相同的逻辑从数据库提供文件。只需替换new FileInputStream()ResultSet#getInputStream()

希望这可以帮助。

2020-06-16