I have a Java web application running on Tomcat. I want to load static images that will be shown both on the Web UI and in PDF files generated by the application. Also new images will be added and saved by uploading via the Web UI.
It's not a problem to do this by having the static data stored within the web container but storing and loading them from outside the web container is giving me headache.
I'd prefer not to use a separate web server like Apache for serving the static data at this point. I also don't like the idea of storing the images in binary in a database.
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?
Some suggest writing a filter or a servlet for handling the image serving but those suggestions have been very vague and high-level without pointers to more detailed information on how to accomplish this.
This question is related to
tomcat
jakarta-ee
servlets
static-content
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
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
)
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.
I did it even simpler. Problem: A CSS file had url links to img folder. Gets 404.
I looked at url, http://tomcatfolder:port/img/blablah.png, which does not exist. But, that is really pointing to the ROOT app in Tomcat.
So I just copied the img folder from my webapp into that ROOT app. Works!
Not recommended for production, of course, but this is for an internal tool dev app.
If you want to work with JAX-RS (e.g. RESTEasy) try this:
@Path("/pic")
public Response get(@QueryParam("url") final String url) {
String picUrl = URLDecoder.decode(url, "UTF-8");
return Response.ok(sendPicAsStream(picUrl))
.header(HttpHeaders.CONTENT_TYPE, "image/jpg")
.build();
}
private StreamingOutput sendPicAsStream(String picUrl) {
return output -> {
try (InputStream is = (new URL(picUrl)).openStream()) {
ByteStreams.copy(is, output);
}
};
}
using javax.ws.rs.core.Response
and com.google.common.io.ByteStreams
Read the InputStream of a file and write it to ServletOutputStream
for sending binary data to the client.
@WebServlet("/files/URLStream")
public class URLStream extends HttpServlet {
private static final long serialVersionUID = 1L;
public URLStream() {
super();
}
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
File source = new File("D:\\SVN_Commit.PNG");
long start = System.nanoTime();
InputStream image = new FileInputStream(source);
/*String fileID = request.getParameter("id");
System.out.println("Requested File ID : "+fileID);
// Mongo DB GridFS - https://stackoverflow.com/a/33544285/5081877
image = outputImageFile.getInputStream();*/
if( image != null ) {
BufferedInputStream bin = null;
BufferedOutputStream bout = null;
ServletOutputStream sos = response.getOutputStream();
try {
bin = new BufferedInputStream( image );
bout = new BufferedOutputStream( sos );
int ch =0; ;
while((ch=bin.read())!=-1) {
bout.write(ch);
}
} finally {
bin.close();
image.close();
bout.close();
sos.close();
}
} else {
PrintWriter writer = response.getWriter();
writer.append("Something went wrong with your request.");
System.out.println("Image not available.");
}
System.out.println("Time taken by Stream Copy = "+(System.nanoTime()-start));
}
}
Result the URL directly to the src
attibute.
<img src='http://172.0.0.1:8080/ServletApp/files/URLStream?id=5a575be200c117cc2500003b' alt="mongodb File"/>
<img src='http://172.0.0.1:8080/ServletApp/files/URLStream' alt="local file"/>
<video controls="controls" src="http://172.0.0.1:8080/ServletApp/files/URLStream"></video>
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>
if anyone not able to resolve his problem with accepted answer, then note these below considerations:
localhost:<port>
with <img> src
attribute.context docBase
entry on its own inside its local server.xml
file.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
Source: Stackoverflow.com