在server.xml我的tomcat文件夹中,我在<Host>标记下有一个虚拟文件夹:
server.xml
<Host>
<Context docBase="C:\app_files\" path="/app_files"/>
因此,我可以通过url从此文件夹中访问文件:http:// localhost:8080 / app_files / some_file.jpg
但这仅在启动服务器之前图像或文件已经存在的情况下才有效。如果我转到一个指向服务器启动后创建的图像的URL,则会出现404错误。重新启动服务器后,映像将正确加载。
如何解决这个问题?
实际上,我确实在不使用server.xml的上下文的情况下完成了我想要的事情。它基于BalusC的解决方案来通过servlet提供静态文件,方法如下:
public String imageUrl; public void createAndShowImage() { try { String imageName = "/nice_images_folder/cool_image.jpg"; File imageFile = new File(System.getenv("MANAGEMENT_FILES") + imageName); //Here goes your logic to create the file createImage(imageFile); //Here i use a fixed URL, you can do it as you see fit this.imageUrl = "http://localhost:8080/MyCoolApp/" + CoolFileServlet.BASE_URL + imageName + "?delete=true"; } catch (Exception e) { e.printStackTrace(); } }
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URLDecoder; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name="CoolFileServlet", urlPatterns={CoolFileServlet.BASE_URL + "*"}) public class CoolFileServlet extends HttpServlet { public static final String BASE_URL = "/shiny_happy_files/"; private static final int DEFAULT_BUFFER_SIZE = 10240; private String filePath; public void init() throws ServletException { this.filePath = System.getenv("MANAGEMENT_FILES"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestedFile = request.getPathInfo(); if (requestedFile == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404. return; } File file = new File(filePath, URLDecoder.decode(requestedFile, "UTF-8")); if (!file.exists()) { response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404. return; } String contentType = getServletContext().getMimeType(file.getName()); if (contentType == null) { contentType = "application/octet-stream"; } response.reset(); response.setBufferSize(DEFAULT_BUFFER_SIZE); response.setContentType(contentType); response.setHeader("Content-Length", String.valueOf(file.length())); response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\""); BufferedInputStream input = null; BufferedOutputStream output = null; try { input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE); output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE); byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; int length; while ((length = input.read(buffer)) > 0) { output.write(buffer, 0, length); } } finally { close(output); close(input); try { if ("true".equals(request.getParameter("delete"))) { if (!file.delete()) { throw new RuntimeException("File could not be deleted"); } } } catch (Exception e) { e.printStackTrace(); } } } private static void close(Closeable resource) { if (resource != null) { try { resource.close(); } catch (IOException e) { e.printStackTrace(); } } } }
请注意,您可以在访问URL时将其参数delete = true传递给url,以便在恢复后立即将其删除(以防万一不再需要它)。
就我而言,我需要在用户执行某些操作后在页面上显示图像,所以我要做的就是显示图像网址:
<h:graphicImage url="#{myManagedBean.imageUrl}"/>
就是这样,您可以使用该servlet提供任何类型的文件,并且该文件将立即返回您想要的文件,并且该文件将在服务器重新启动/重新部署之间保持活动状态(如果未通过删除)delete=true。
delete=true