我有一个在Tomcat上运行的Java Web应用程序。我想加载静态图像,这些图像将同时显示在Web UI和应用程序生成的PDF文件中。通过Web UI上载还将添加和保存新图像。
通过将静态数据存储在Web容器中来执行此操作不是问题,但是从Web容器外部存储和加载静态数据让我头疼。
我现在不希望使用像Apache这样的单独的Web服务器来提供静态数据。我也不喜欢将图像以二进制形式存储在数据库中的想法。
我已经看到了一些建议,例如将图像目录作为指向Web容器外部目录的符号链接,但是这种方法在Windows和* nix环境下都可以使用吗?
有些人建议编写一个用于处理图像服务的过滤器或Servlet,但是这些建议非常模糊且笼统,没有指向如何实现此目的的更详细信息的指针。
如果您遵循* nix文件系统路径规则(即,您仅使用中的正斜杠/path/to/files),那么它也将在Windows上运行,而无需摆弄丑陋的File.separator字符串连接。但是,只能在与调用该命令的位置相同的工作磁盘上对其进行扫描。因此,例如如果安装了Tomcat,C:则/path/to/files实际指向C:\path\to\files。
/path/to/files
File.separator
C:
C:\path\to\files
如果这些文件都位于webapp之外,并且您想让Tomcat DefaultServlet处理这些文件,那么在Tomcat中,您基本上要做的就是将以下Context元素添加到/conf/server.xmlinside <Host>标记中:
DefaultServlet
/conf/server.xml
<Host>
<Context docBase="/path/to/files" path="/files" />
这样,就可以通过访问它们http://example.com/files/...。GlassFish / Payara配置示例如果您想自己控制文件的读写,那么您需要为此创建一个Servlet,它基本上只是InputStream以例如的形式获取文件的FileInputStream并将其写入的OutputStream中HttpServletResponse。
http://example.com/files/...
Servlet
InputStream
FileInputStream
OutputStream
HttpServletResponse
在响应上,您应该设置Content-Type标题,以便客户端知道要与提供的文件关联的应用程序。并且,您应该设置Content- Length标题,以便客户端可以计算下载进度,否则它将是未知的。并且,如果需要“ 另存为” 对话框,则应将Content- Disposition标题设置为,否则客户端将尝试内联显示它。最后,只需将文件内容写入响应输出流即可。attachment __
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在“ 另存为” 期间将不会选择正确的文件名。
url- pattern
/files/*
http://example.com/files/image.png
if(!file.exists()) file = new File("/path/to/files","404.gif")
request.getPathInfo()
request.getParameter()
您可以重复使用相同的逻辑从数据库提供文件。只需替换new FileInputStream()为ResultSet#getInputStream()。
new FileInputStream()
ResultSet#getInputStream()
希望这可以帮助。