我有一个在Tomcat上运行的Java Web应用程序。我想加载静态图像,这些图像将同时显示在Web UI和应用程序生成的PDF文件中。通过Web UI上载也可以添加和保存新图像。
通过将静态数据存储在Web容器中来做到这一点不是问题,但是从Web容器外部存储和加载它们使我头疼。
我现在不希望使用像Apache这样的单独的Web服务器来提供静态数据。我也不喜欢将图像以二进制形式存储在数据库中的想法。
我已经看到一些建议,例如将图像目录作为指向Web容器外部目录的符号链接,但是这种方法会在Windows和* nix环境下都可以工作吗? br />

#1 楼


我已经看到一些建议,例如将图像目录作为指向Web容器外部目录的符号链接,但是这种方法在Windows和* nix环境下都可以使用吗?如果您遵循* nix文件系统路径规则(即,您仅在/path/to/files中使用正斜杠),则它也将在Windows上运行,而无需费心处理File.separator字符串串联。但是,只能在与调用该命令的位置相同的工作磁盘上对其进行扫描。因此,例如,如果在C:上安装了Tomcat,则/path/to/files实际上将指向C:\path\to\files
如果文件都位于Web应用程序外部,并且您想让Tomcat的DefaultServlet来处理它们,那么您基本上要做的就是在Tomcat中,是在/conf/server.xml标签内的<Host>中添加以下Context元素: 。对于基于Tomcat的服务器(例如JBoss EAP 6.x或更早版本),方法基本相同,另请参见此处。 GlassFish / Payara配置示例可以在此处找到,WildFly配置示例可以在此处找到。
如果您想自己控制文件的读写,则需要为此创建一个<Context docBase="/path/to/files" path="/files" /> ,基本上可以得到一个http://example.com/files/...Servlet之类的文件格式添加文件,并将其写入到InputStreamFileInputStream中。
在响应上,您应该设置OutputStream标头,以便客户端知道要与提供的文件关联的应用程序。并且,您应该设置HttpServletResponse标头,以便客户端可以计算下载进度,否则它将是未知的。并且,如果需要“另存为”对话框,则应将Content-Type标头设置为Content-Length,否则客户端将尝试内联显示它。最后,只需将文件内容写入响应输出流即可。
这是这种servlet的基本示例:这样,您可以比Content-Disposition更好地控制请求,例如提供默认图片(即attachment左右)。在url-pattern之前,还优先使用/files/*,因为它对SEO更友好,否则IE在另存为时将不会选择正确的文件名。只需将http://example.com/files/image.png替换为DefaultServlet
希望这会有所帮助。静态资源Servlet(支持HTTP缓存)
如何在JSP页面中从数据库检索和显示图像?
如何使用Servlet来流化音频/视频文件,例如MP3,MP4,AVI等


评论


@SalutonMondo:省力的方式。

– BalusC
2015年2月11日下午13:30

@BalusC,我尝试了此操作:Windows中的,但获取相对于webapps文件夹的路径:C:\ install \ apache-tomcat-8.0。 26 \ webapps \ tmp]无效

– ACV
2015年9月12日在16:50



在Windows上,应为:

– ACV
2015年9月12日在16:52

并在执行以下操作时获取HTTP Status 404-/ images /:http:// localhost:8080 / images /,但是从tmp下运行特定文件:http:// localhost:8080 / images / Tulips.jpg可以

– ACV
2015年9月12日16:55



这样,如果我将图像放在文件夹中,除非重新启动服务器,否则图像的链接将给出响应404,请问有什么原因吗?

– Mateus Viccari
16年4月1日在12:28

#2 楼

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


或者如果您想操作图像: />,那么html代码将是<img src="imageServlet?imageName=myimage.png" />

当然,您应该考虑提供不同的内容类型-例如“ image / jpeg”,例如基于文件扩展名。此外,您还应该提供一些缓存。

此外,您还可以通过提供width和height参数作为参数,并使用image.getScaledInstance(w, h, Image.SCALE_SMOOTH),当然也要考虑性能,从而可以将此servlet用于图像的质量缩放。 br />

评论


您确实不需要Java 2D API,它只会不必要地增加更多开销。只需读取InputStream并写入OutputStream。

– BalusC
09年11月28日在11:44

是的,我以重新缩放和其他操作的想法开始了响应,但最终简化了它。

– Bozho
09年11月28日在11:59

#3 楼

添加到server.xml中:

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


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

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


评论


通过更改web.xml,我可以获取文件列表,以便将其发送到选择框?

– Tomasz Waszczyk
16-11-21在7:54

此更改将在tomcat的web.xml中,而不是您的应用程序中

–vsingh
17年11月13日在21:24

谢谢你!是否需要在web.xml中启用dir文件列表参数?

– dariru
18年9月7日在2:52

#4 楼

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

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

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

代码。 />
<web-app>
</web-app>


以上两个步骤的目录结构

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


步骤3:
现在创建一个xml位于以下位置的名称为myproj.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驱动器中创建一个名为myproj的文件夹,并创建一个带有名称图像的新

文件夹,并将一些图像放置在图像中文件夹(e:myproj\images\)

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

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

web.xml中的代码

<web-app>
</web-app>


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

index.html下的代码


欢迎使用Myproj



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

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


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

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

http://localhost:8080/myproj    


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

步骤8:访问本地硬盘(位于Webroot外部)下的图像

http://localhost:8080/myproj/images/myfoto.jpg


评论


您能建议我如何为动态值做同样的事情吗?我的意思是我想将data(xml)写入本地目录或和并在我的jsp页面中读取它。有什么方法可以写入托管到目录的服务器,以便我可以使用上述过程访问它们?

– Sudip7
2014年11月21日在13:03

尽管我可以正常运行index.html文件,但Web浏览器中无法显示图像

–rogerwar
2015年5月29日3:00

我的错误帖子可以正常工作,我只是忘了把/放在E:/ myproj的末尾,我将其更改为E:/ myproj /及其工作正常,谢谢@sbabamca

–rogerwar
15年5月29日在3:08



嗨,感谢您的帖子,这非常有用。在这里,我希望通过接口将文件上传到该特定目录。我希望同样启用POST方法。有人可以帮我吗?

–vicky
15年6月13日在10:58



#5 楼

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

以下解决方案非常简单,可以有效地满足要求(*):

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

结果:我们已经创建了2个别名。例如,我们将图像保存在:D:\images\foo.jpg
,并从链接或使用图像标签查看: br />
(我使用Netbeans 7.x,Netbeans似乎自动创建了文件WEB-INF\context.xml

#6 楼

如果您决定分派给FileServlet,则还需要allowLinking="true"中的context.xml,以允许FileServlet遍历符号链接。

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

#7 楼

如果任何人都无法通过接受的答案解决他的问题,请注意以下注意事项:


无需使用localhost:<port>属性提及<img> src。 eclipse之外,因为eclipse会在其本地context docBase文件内自行创建server.xml条目。


#8 楼

读取文件的InputStream并将其写入ServletOutputStream,以将二进制数据发送到客户端。 .png')。

,您可以使用GridFS获得InputStream。

br />



直接将URL生成到@WebServlet("/files/URLStream") public class URLStream extends HttpServlet { private static final long serialVersionUID = 1L; public URLStream() { super(); } protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { File source = new File("D:\SVN_Commit.PNG"); long start = System.nanoTime(); InputStream image = new FileInputStream(source); /*String fileID = request.getParameter("id"); System.out.println("Requested File ID : "+fileID); // Mongo DB GridFS - https://stackoverflow.com/a/33544285/5081877 image = outputImageFile.getInputStream();*/ if( image != null ) { BufferedInputStream bin = null; BufferedOutputStream bout = null; ServletOutputStream sos = response.getOutputStream(); try { bin = new BufferedInputStream( image ); bout = new BufferedOutputStream( sos ); int ch =0; ; while((ch=bin.read())!=-1) { bout.write(ch); } } finally { bin.close(); image.close(); bout.close(); sos.close(); } } else { PrintWriter writer = response.getWriter(); writer.append("Something went wrong with your request."); System.out.println("Image not available."); } System.out.println("Time taken by Stream Copy = "+(System.nanoTime()-start)); } } 礼节。



 src 


#9 楼

如果要使用JAX-RS(例如RESTEasy),请尝试以下操作:

@Path("/pic")
public Response get(@QueryParam("url") final String url) {
    String picUrl = URLDecoder.decode(url, "UTF-8");

    return Response.ok(sendPicAsStream(picUrl))
            .header(HttpHeaders.CONTENT_TYPE, "image/jpg")
            .build();
}

private StreamingOutput sendPicAsStream(String picUrl) {
    return output -> {
        try (InputStream is = (new URL(picUrl)).openStream()) {
            ByteStreams.copy(is, output);
        }
    };
}


使用javax.ws.rs.core.Responsecom.google.common.io.ByteStreams

#10 楼

我做得更简单。问题:CSS文件具有指向img文件夹的URL链接。获取404。

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

所以我只是将img文件夹从我的Web应用程序复制到了该ROOT应用程序中。作品!

当然不建议用于生产,但这是针对内部工具开发应用程序的。