So I recently got a contract to create a website that would function similar to kijiji or craigslist. This particular site is to be constructed around a particular niche. I was confident in my ability to create this website in a reasonable amount of time, but I hadn’t planned on one particular part causing me so much grief. This is usually the case with any programming project, there’s always something that will slow you down. So I’m posting this content to help you if you’re in the same situation.
Here’s the breakdown of the workflow.
User A Uploads Pictures -> Pictures are stored on server -> User B loads website -> User B sees pictures from User A
Pretty simple workflow right? Well, apparently it wasn’t so simple. Here’s the places I went wrong:
- I tried to link the <img> tags straight to the server’s image folder like so:
<img src="c:/server/images/img1.jpg" />
- It’s a no go, modern browsers these days don’t let you refer to a directory on a server like this (fail)
- I tried to create a servlet that would map a particular directory (i.e. /myApp/images/) to a controller and then return a byte array with the contents of the image
- Okay, so this sort of worked. But the main issue was that it wouldn’t really cache the images, so every single time you hit the page, it would reload each of the images, and that really killed the user experience of my page (fail)
- I tried storing the images in my database and retrieving them via a servlet, but this was just as useful as attempt #2 above. (fail)
Here’s the correct solution that I finally landed on. You need to setup a context path for your webapp. Here’s how I did it:
First, you need to create an xml file that will define your context path, like so: (Success!)
So this file, named WoodworkingExchange#thumbs.xml (for good reason) maps the path ‘/WoodworkingExchange/thumbs’ to a physical location on my server ‘c:\DEV_ECOSIM\thumbs’.
Now, the location of this file, and the name of this file is critical. The location must be inside of your tomcat’s conf\Catalina\localhost directory. Now, this is a common setup for most people, though if you have a different engine and host name then you’ll have to change the directories. The file name is named after the name of the webapp, in the case WoodworkingExchange (this is the name of the application that’s deployed in my webapps folder). But then I have a hashtag (#) and the name thumbs… this is what maps ‘WoodworkingExchange/thumbs’ path, the hashtag (#) is a placeholder for the forward slash (/). So, if I wanted to choose a different location for my images, like say ‘WoodworkingExchange/images’, I would name my XML file “WoodworkingExchange#images.xml”, and inside the file, I would replace the path=”/WoodworkingExchange/thumbs” with path=”/WoodworkingExchange/images”.
Here’s an excerpt from the Apache Tomcat documentation (http://tomcat.apache.org/tomcat-5.5-doc/config/context.html):
Context elements may be explicitly defined:
- In the
$CATALINA_HOME/conf/context.xmlfile: the Context element information will be loaded by all webapps.
- In the
$CATALINA_HOME/conf/[enginename]/[hostname]/context.xml.defaultfile: the Context element information will be loaded by all webapps of that host.
- In individual files (with a “.xml” extension) in the
$CATALINA_HOME/conf/[enginename]/[hostname]/directory. The name of the file (less the .xml) extension will be used as the context path. Multi-level context paths may be defined using #, e.g.
foo#bar.xmlfor a context path of
/foo/bar. The default web application may be defined by using a file called
- Only if a context file does not exist for the application in the
$CATALINA_HOME/conf/[enginename]/[hostname]/; in an individual file at
/META-INF/context.xmlinside the application files. If the web application is packaged as a WAR then
/META-INF/context.xmlwill be copied to
$CATALINA_HOME/conf/[enginename]/[hostname]/and renamed to match the application’s context path. Once this file exists, it will not be replaced if a new WAR with a newer
/META-INF/context.xmlis placed in the host’s appBase.
- inside a Host element in the main
The approach I took here is in the third bullet above (where we have individual XML files. So, now in my JSP files, I can just reference images like so:
<img src="WoodworkingExchange/thumbs/image.PNG" width="175px"/>
And Voila, they’ll show up!