一尘不染

服务器启动后,Tomcat无法从上下文路径加载新图像

tomcat

server.xml我的tomcat文件夹中,我在<Host>标记下有一个虚拟文件夹:

<Context docBase="C:\app_files\" path="/app_files"/>

因此,我可以通过url从此文件夹中访问文件:http:// localhost:8080 / app_files /
some_file.jpg

但这仅在启动服务器之前图像或文件已经存在的情况下才有效。如果我转到一个指向服务器启动后创建的图像的URL,则会出现404错误。重新启动服务器后,映像将正确加载。

如何解决这个问题?


阅读 276

收藏
2020-06-16

共1个答案

一尘不染

实际上,我确实在不使用server.xml的上下文的情况下完成了我想要的事情。它基于BalusC的解决方案来通过servlet提供静态文件,方法如下:

  • 首先,我在系统中创建了一个环境变量 (可以在每个操作系统中完成,只需在Google上搜索“如何在Windows,Linux等上创建环境变量”) ,称为 MANAGEMENT_FILES ,在我的情况下,变量值为 c:/ management_files /
  • 然后,在创建应显示给用户的图像的方法上,我将图像保存在此文件夹中 (这是上一步中环境变量的值)
    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();
        }
    }
  • 这是您必须创建的servlet,此servlet返回图像或放置在文件夹中的任何其他文件:
    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

2020-06-16