Okay so I figured out the answer. It turns out that to load an image, you actually need Java code to write out the binary data via a BufferedOutputStream (being a total newbie, I had thought that Tomcat would take care of that for me).
Concretely, you need a servlet to actually convert a path like "/images/logo.jpg" in your HTML into a usable image. The servlet is called via a servlet mapping of /images/* to the servlet. By extracting the * part of /images/* , we are able to get the exact image name, and then the servlet can load it.
Here's the servlet mapping (to be added to WEB-INF/web.xml
):
...
<servlet>
<servlet-name>DisplayImage</servlet-name>
<servlet-class>servlets.DisplayImage</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DisplayImage</servlet-name>
<url-pattern>/images/*</url-pattern>
</servlet-mapping>
...
Note that in my project, DisplayImage is found in C:/.../Entertainment_mgmt/src/servlets/DisplayImage.java
.
Of course, you can add whatever you want in your mapping. The mapping is what is seen in the URL, as in localhost:8040/images/logo.jpg
or inside an HTML page as <img src="/images/logo.jpg" />
. From the point of servlets, both are the same thing. As per the mapping above, both are handled by the servlet DisplayImage.
I found some code for the DisplayImage servlet here. I've modified it a bit:
package servlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class DisplayImage extends HttpServlet {
public final String imagesBase = "F:\\Workspaces\\Java\\Projects\\Entertainment_mgmt\\src\\images/";
public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException{
String URLAfterWebDomain = request.getRequestURI();
//Only accept mappings as src="/images/whatever.jpg", even if web.xml has other mappings to this servlet.
if(URLAfterWebDomain.startsWith("/images/") == false)
return;
//get the image name, or even directory and image, e.g. /images/music/beethoven.jpg:
String relativeImagePath = URLAfterWebDomain.substring("/images/".length()); //will get "music/beethoven.jpg"
System.out.println("\nFetching image from "+imagesBase+relativeImagePath);
response.setContentType("image/jpeg"); //as far as I know, this works for PNG as well. You might want to change the mapping to /images/*.jpg if it's giving problems
ServletOutputStream outStream;
outStream = response.getOutputStream();
FileInputStream fin = new FileInputStream(imagesBase+relativeImagePath);
BufferedInputStream bin = new BufferedInputStream(fin);
BufferedOutputStream bout = new BufferedOutputStream(outStream);
int ch =0; ;
while((ch=bin.read())!=-1)
bout.write(ch);
bin.close();
fin.close();
bout.close();
outStream.close();
}
}
You can set imagesBase
to any folder on your computer, it doesn't have to be in your project folder. You can also change the name of the /images/
folder to /pics/
or whatever.
Now, whenever I put an <img>
tag in an HTML, I can use src="/images/whatever.jpg"
attribute to call the DisplayImage servlet and show the image. That image can then be repositioned, etc.
This can even be done inside other servlets which write out HTML. In that case, the servlets are called independently and output over HTTP independently (this is why in some web pages, the text loads first and the image loads later).