我实际上设法在不使用 server.xml 上的上下文的情况下做我想做的事。
它基于BalusC's solution 通过servlet 提供静态文件
方法如下:
- 首先,我在我的系统中创建了一个环境变量(可以在每个操作系统中完成,只需谷歌“如何在 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.