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

Jan*_*nne 129 tomcat servlets static-content java-ee

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

通过将静态数据存储在Web容器中但从Web容器外部存储和加载它们来解决这个问题并不是一个问题.

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

我已经看到一些建议,比如将图像目录作为指向Web容器外部目录的符号链接,但这种方法是否适用于Windows和*nix环境?

有人建议编写一个过滤器或servlet来处理图像服务,但这些建议非常模糊和高级别,没有指向如何实现这一目标的更详细信息.

Bal*_*usC 159

我已经看到一些建议,比如将图像目录作为指向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.xml内部<Host>标记中:

<Context docBase="/path/to/files" path="/files" />
Run Code Online (Sandbox Code Playgroud)

这样他们就可以通过http://example.com/files/....GlassFish的/似鲭水狼牙鱼配置例子可以发现这里和WildFly配置示例可以找到这里.

如果你想拥有超过读取控制/写文件自己,那么你需要创建一个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());
    }

}
Run Code Online (Sandbox Code Playgroud)

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

希望这可以帮助.

也可以看看:


Boz*_*zho 9

您可以将图像放在固定路径上(例如:/ 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);
}
Run Code Online (Sandbox Code Playgroud)

或者如果你想操纵图像:

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());
Run Code Online (Sandbox Code Playgroud)

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

当然,您应该考虑提供不同的内容类型 - "image/jpeg",例如基于文件扩展名.你也应该提供一些缓存.

此外,您可以使用此servlet对图像进行质量重新缩放,通过提供宽度和高度参数作为参数,并使用image.getScaledInstance(w, h, Image.SCALE_SMOOTH),当然,考虑性能.

  • 你真的不需要Java 2D API,它只会不必要地增加更多的开销.只需读取一个InputStream并写入OutputStream即可. (2认同)

小智 6

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

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

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

web.xml下的代码

<web-app>
</web-app>
Run Code Online (Sandbox Code Playgroud)

上述两个步骤的目录结构

c:\programfile\apachesoftwarefoundation\tomcat\...\webapps
                                                            |
                                                            |---myproj
                                                            |   |
                                                            |   |---WEB-INF
                                                                |   |
                                                                    |---web.xml
Run Code Online (Sandbox Code Playgroud)

步骤3:
现在在以下位置创建名为myproj.xml的xml文件

c:\programfile\apachesoftwarefoundation\tomcat\conf\catalina\localhost
Run Code Online (Sandbox Code Playgroud)

myproj.xml中的CODE:

<Context path="/myproj/images" docBase="e:/myproj/" crossContext="false" debug="0" reloadable="true" privileged="true" /> 
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

web.xml中的代码

<web-app>
</web-app>
Run Code Online (Sandbox Code Playgroud)

步骤5:
现在创建一个名为index.html的.html文档,并放在e:\ myproj下

index.html下的CODE欢迎使用Myproj

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

E:\myproj
    |--index.html
    |
    |--images
    |     |----myfoto.jpg
    |
    |--WEB-INF
    |     |--web.xml
Run Code Online (Sandbox Code Playgroud)

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

步骤7:
打开浏览器并按如下方式键入URL

http://localhost:8080/myproj    
Run Code Online (Sandbox Code Playgroud)

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

步骤8:
访问本地硬盘下的图像(webroot之外)

http://localhost:8080/myproj/images/myfoto.jpg
Run Code Online (Sandbox Code Playgroud)


nhu*_*uvy 6

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

以下解决方案非常简单,对需求(*)有效:

在包含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"/>
Run Code Online (Sandbox Code Playgroud)

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

结果:我们创建了2个别名.例如,我们将图像保存在:D:\images\foo.jpg 和链接或使用图像标记查看:

<img src="http://localhost:8080/ABC/images/foo.jsp" alt="Foo" height="142" width="142">
Run Code Online (Sandbox Code Playgroud)

要么

<img src="/images/foo.jsp" alt="Foo" height="142" width="142">
Run Code Online (Sandbox Code Playgroud)

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


blu*_*sky 5

添加到server.xml:

 <Context docBase="c:/dirtoshare" path="/dir" />
Run Code Online (Sandbox Code Playgroud)

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

    <init-param>
        <param-name>listings</param-name>
        <param-value>true</param-value>
    </init-param>
Run Code Online (Sandbox Code Playgroud)