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

我有一个Java Web应用程序,使用Spring和Struts,运行在Tomcat 5.5上。 我想加载静态图像,这些图像将显示在Web UI和应用程序生成的PDF文件中。 此外,新的图像将通过Web UI进行上传和保存。

通过将静态数据存储在Web容器中,但是从Web容器外部存储和加载静态数据,这不是一个问题,这让我很头痛。

我宁愿不使用像Apache这样的单独的Web服务器来为静态数据提供服务。 我也不喜欢在二进制数据库中存储图像的想法。

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

有些人build议编写一个filter或一个servlet来处理图像服务,但是这些build议非常模糊和高层次,没有提供关于如何完成这个任务的更详细信息的指针。

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

如果您坚持* nix文件系统path规则(即,您在/path/to/files使用专用正斜杠),那么它也可以在Windows上工作,而无需摆弄丑陋的File.separatorstring连接。 但是,只能在与调用该命令相同的工作磁盘上进行扫描。 因此,如果Tomcat安装在C:那么/path/to/files实际上会指向C:\path\to\files

如果这些文件都位于webapp外部,并且您希望让Tomcat的DefaultServlet来处理它们,那么您在Tomcat中基本上需要做的就是将以下Context元素添加到<Host>标记内的/conf/server.xml

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

这样他们将可以通过http://example.com/files/...进行访问。 GlassFish / Payaraconfiguration示例可以在这里find,而WildFlyconfiguration示例可以在这里find。

如果你想自己控制读/写文件,那么你需要为此创build一个Servlet ,它基本上只是获得FileInputStream的文件的InputStream ,并将其写入到HttpServletResponseOutputStream中。

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

这是一个这样的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()因为它更适合search引擎优化,否则在另存为期间IE不会select正确的文件名。

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

希望这可以帮助。

也可以看看:

  • 将上传的文件保存在servlet应用程序中的推荐方法
  • 静态资源servlet的抽象模板 (支持HTTPcaching)
  • 如何从JSP页面中的数据库中检索和显示图像?
  • 如何使用Servletstream式传输audio/video文件,如MP3,MP4,AVI等

你可以把你的图像放在一个固定的path上(例如:/ var / images,或c:\ images),在你的应用程序设置中添加一个设置(在我的例子中用Settings.class表示),然后加载就像那样,在你的HttpServlet中:

 String filename = Settings.getValue("images.path") + request.getParameter("imageName") FileInputStream fis = new FileInputStream(filename); int b = 0; while ((b = fis.read()) != -1) { response.getOutputStream().write(b); } 

或者如果你想操纵图像:

 String filename = Settings.getValue("images.path") + request.getParameter("imageName") File imageFile = new File(filename); BufferedImage image = ImageIO.read(imageFile); ImageIO.write(image, "image/png", response.getOutputStream()); 

那么html代码将是<img src="imageServlet?imageName=myimage.png" />

当然,您应该考虑提供不同的内容types – 例如基于文件扩展名的“image / jpeg”。 你也应该提供一些caching。

另外,你可以使用这个servlet对图像进行质量重定标,提供宽度和高度参数作为参数,当然也可以使用image.getScaledInstance(w, h, Image.SCALE_SMOOTH )来考虑性能。

要求:从WEBROOT目录或本地磁盘外部访问静态资源(图像/video等)

步骤1 :
在tomcat服务器的webapps下创build一个文件夹,让我们说文件夹名是myproj

第2步 :
在myproj下创build一个WEB-INF文件夹下创build一个简单的web.xml

代码在web.xml下

 <web-app> </web-app> 

目录结构为以上两个步骤

 c:\programfile\apachesoftwarefoundation\tomcat\...\webapps | |---myproj | | | |---WEB-INF | | |---web.xml 

第3步:
现在在下面的位置下创build名称为myproj.xml的xml文件

 c:\programfile\apachesoftwarefoundation\tomcat\conf\catalina\localhost 

在myproj.xml中的代码:

 <Context path="/myproj/images" docBase="e:/myproj/" crossContext="false" debug="0" reloadable="true" privileged="true" /> 

步骤4:
4 A)现在在硬盘的E驱动器中创build一个名称为myproj的文件夹,并创build一个新的文件夹

文件夹名称的图像,并放置在图像文件夹(e:myproj\images\)一些图像

让我们假设myfoto.jpg放在e:\myproj\images\myfoto.jpg

4 B)现在在e:\myproj\WEB-INF创build一个名为WEB-INF的文件夹,并在WEB-INF文件夹中创build一个web.xml文件

在web.xml中的代码

 <web-app> </web-app> 

第5步:
现在创build一个名为index.html的.html文件,放在e:\ myproj下

index.html下的CODE欢迎来到Myproj

上述步骤4和步骤5的目录结构如下

 E:\myproj |--index.html | |--images | |----myfoto.jpg | |--WEB-INF | |--web.xml 

第六步:
现在启动apache tomcat服务器

第七步:
打开浏览器并按如下所示键入url

 http://localhost:8080/myproj 

然后显示index.html中提供的内容

第八步:
要访问本地硬盘(webroot之外)下的图像,

 http://localhost:8080/myprojhttp://img.dovov.commyfoto.jpg 

添加到server.xml:

  <Context docBase="c:/dirtoshare" path="/dir" /> 

在web.xml中启用dir文件列表参数:

  <init-param> <param-name>listings</param-name> <param-value>true</param-value> </init-param> 

这是来自我工作场所的故事:
– 我们尝试使用Struts 1和Tomcat 7.x来上传多个图像和文档文件。
– 我们尝试将上传的文件写入文件系统,文件名和数据库logging的完整path。
– 我们尝试在Web应用程序目录之外分开文件夹 。 (*)

以下解决scheme非常简单,对要求(*)有效:

在具有以下内容的META-INF/context.xml文件中:(例如,我的应用程序运行在http://localhost:8080/ABC ,我的应用程序/项目名为ABC )。 (这也是文件context.xml完整内容)

 <?xml version="1.0" encoding="UTF-8"?> <Context path="/ABC" aliases="/images=D:\images,/docs=D:\docs"/> 

(适用于Tomcat版本7或更高版本)

结果:我们已经创build了2个别名。 例如,我们将图像保存在: D:\images\foo.jpg并从链接查看或使用图像标签:

 <img src="http://localhost:8080/ABChttp://img.dovov.comfoo.jsp" alt="Foo" height="142" width="142"> 

要么

 <img src="http://img.dovov.comfoo.jsp" alt="Foo" height="142" width="142"> 

(我使用Netbeans 7.x,Netbeans似乎是自动创build文件WEB-INF\context.xml

如果您决定分派到FileServlet那么您还需要在context.xml中使用allowLinking="true" ,以便允许FileServlet遍历符号链接。

请参阅http://tomcat.apache.org/tomcat-6.0-doc/config/context.html

我做得更简单。 问题:一个CSS文件有链接到img文件夹的URL。 获取404。

我看了一下url, http:// tomcatfolder:port / img / blablah.png ,它不存在。 但是,这实际上是指向Tomcat中的ROOT应用程序。

所以我只是从我的web应用程序复制img文件夹到ROOT应用程序。 作品!

当然不build议用于生产,但这是一个内部工具开发应用程序。

如果有人无法用接受的答案解决他的问题,请注意以下几点:

  1. 不需要提及localhost:<port><img> src属性。
  2. 确保你在eclipse之外运行这个项目,因为eclipse在它的本地server.xml文件内部自己创build了context docBase条目。