Tomcat will serve any static content from a WAR file using the DefaultServlet.
Simply put, Apache HTTP server is a web server designed to serve static web pages. Whereas, Apache Tomcat is an application server built to serve java applications. Web pages can still be served through Apache Tomcat, but it will be less efficient than using an Apache HTTP server.
I've seen some suggestions like having the image directory being a symbolic link pointing to a directory outside the web container, but will this approach work both on Windows and *nix environments?
If you adhere the *nix filesystem path rules (i.e. you use exclusively forward slashes as in /path/to/files
), then it will work on Windows as well without the need to fiddle around with ugly File.separator
string-concatenations. It would however only be scanned on the same working disk as from where this command is been invoked. So if Tomcat is for example installed on C:
then the /path/to/files
would actually point to C:\path\to\files
.
If the files are all located outside the webapp, and you want to have Tomcat's DefaultServlet
to handle them, then all you basically need to do in Tomcat is to add the following Context element to /conf/server.xml
inside <Host>
tag:
<Context docBase="/path/to/files" path="/files" />
This way they'll be accessible through http://example.com/files/...
. For Tomcat-based servers such as JBoss EAP 6.x or older, the approach is basically the same, see also here. GlassFish/Payara configuration example can be found here and WildFly configuration example can be found here.
If you want to have control over reading/writing files yourself, then you need to create a Servlet
for this which basically just gets an InputStream
of the file in flavor of for example FileInputStream
and writes it to the OutputStream
of the HttpServletResponse
.
On the response, you should set the Content-Type
header so that the client knows which application to associate with the provided file. And, you should set the Content-Length
header so that the client can calculate the download progress, otherwise it will be unknown. And, you should set the Content-Disposition
header to attachment
if you want a Save As dialog, otherwise the client will attempt to display it inline. Finally just write the file content to the response output stream.
Here's a basic example of such a servlet:
@WebServlet("/files/*")
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String filename = URLDecoder.decode(request.getPathInfo().substring(1), "UTF-8");
File file = new File("/path/to/files", filename);
response.setHeader("Content-Type", getServletContext().getMimeType(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}
When mapped on an url-pattern
of for example /files/*
, then you can call it by http://example.com/files/image.png
. This way you can have more control over the requests than the DefaultServlet
does, such as providing a default image (i.e. if (!file.exists()) file = new File("/path/to/files", "404.gif")
or so). Also using the request.getPathInfo()
is preferred above request.getParameter()
because it is more SEO friendly and otherwise IE won't pick the correct filename during Save As.
You can reuse the same logic for serving files from database. Simply replace new FileInputStream()
by ResultSet#getInputStream()
.
Hope this helps.
You can do it by putting your images on a fixed path (for example: /var/images, or c:\images), add a setting in your application settings (represented in my example by the Settings.class), and load them like that, in a HttpServlet
of yours:
String filename = Settings.getValue("images.path") + request.getParameter("imageName")
FileInputStream fis = new FileInputStream(filename);
int b = 0;
while ((b = fis.read()) != -1) {
response.getOutputStream().write(b);
}
Or if you want to manipulate the image:
String filename = Settings.getValue("images.path") + request.getParameter("imageName")
File imageFile = new File(filename);
BufferedImage image = ImageIO.read(imageFile);
ImageIO.write(image, "image/png", response.getOutputStream());
then the html code would be <img src="imageServlet?imageName=myimage.png" />
Of course you should think of serving different content types - "image/jpeg", for example based on the file extension. Also you should provide some caching.
In addition you could use this servlet for quality rescaling of your images, by providing width and height parameters as arguments, and using image.getScaledInstance(w, h, Image.SCALE_SMOOTH
), considering performance, of course.
Requirement : Accessing the static Resources (images/videos., etc.,) from outside of WEBROOT directory or from local disk
Step 1 :
Create a folder under webapps of tomcat server., let us say the folder name is myproj
Step 2 :
Under myproj create a WEB-INF folder under this create a simple web.xml
code under web.xml
<web-app>
</web-app>
Directory Structure for the above two steps
c:\programfile\apachesoftwarefoundation\tomcat\...\webapps
|
|---myproj
| |
| |---WEB-INF
| |
|---web.xml
Step 3:
Now create a xml file with name myproj.xml under the following location
c:\programfile\apachesoftwarefoundation\tomcat\conf\catalina\localhost
CODE in myproj.xml:
<Context path="/myproj/images" docBase="e:/myproj/" crossContext="false" debug="0" reloadable="true" privileged="true" />
Step 4:
4 A) Now create a folder with name myproj in E drive of your hard disk and create a new
folder with name images and place some images in images folder (e:myproj\images\)
Let us suppose myfoto.jpg is placed under e:\myproj\images\myfoto.jpg
4 B) Now create a folder with name WEB-INF in e:\myproj\WEB-INF
and create a web.xml in WEB-INF folder
Code in web.xml
<web-app>
</web-app>
Step 5:
Now create a .html document with name index.html and place under e:\myproj
CODE under index.html Welcome to Myproj
The Directory Structure for the above Step 4 and Step 5 is as follows
E:\myproj
|--index.html
|
|--images
| |----myfoto.jpg
|
|--WEB-INF
| |--web.xml
Step 6:
Now start the apache tomcat server
Step 7:
open the browser and type the url as follows
http://localhost:8080/myproj
then u display the content which is provided in index.html
Step 8:
To Access the Images under your local hard disk (outside of webroot)
http://localhost:8080/myproj/images/myfoto.jpg
Add to server.xml :
<Context docBase="c:/dirtoshare" path="/dir" />
Enable dir file listing parameter in web.xml :
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
This is story from my workplace:
- We try to upload multiply images and document files use Struts 1 and Tomcat 7.x.
- We try to write uploaded files to file system, filename and full path to database records.
- We try to separate file folders outside web app directory. (*)
The below solution is pretty simple, effective for requirement (*):
In file META-INF/context.xml
file with the following content:
(Example, my application run at http://localhost:8080/ABC
, my application / project named ABC
).
(this is also full content of file context.xml
)
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/ABC" aliases="/images=D:\images,/docs=D:\docs"/>
(works with Tomcat version 7 or later)
Result: We have been created 2 alias. For example, we save images at: D:\images\foo.jpg
and view from link or using image tag:
<img src="http://localhost:8080/ABC/images/foo.jsp" alt="Foo" height="142" width="142">
or
<img src="/images/foo.jsp" alt="Foo" height="142" width="142">
(I use Netbeans 7.x, Netbeans seem auto create file WEB-INF\context.xml
)
If you decide to dispatch to FileServlet
then you will also need allowLinking="true"
in context.xml
in order to allow FileServlet
to traverse the symlinks.
See http://tomcat.apache.org/tomcat-6.0-doc/config/context.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With