Output an Image File from a Servlet

Output an image file from a servlet

  • map a servlet to the /file url-pattern
  • read the file from disk
  • write it to response.getOutputStream()
  • set the Content-Type header to image/png (if it is only pngs)

How to output an image on file as an HTML img from a Java Servlet?

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).

Creating an outputstream of image in a servlet. How to display it on receiving

If you can already get the image in the browser by directing calling the servlet URL then all you have to do is put an img tag and put the servlet URL in it's src attribute.

<div>
<img src="http://host:port/contextName/servlet-url">
</div>

This will make a GET request to your server and display the downloaded content inside <img>.

Image from servlet cant be opened with browser

An image is binary data. But you are reading it from the resource as characters. Then you are writing those characters as bytes. The result is that you are mangling the image.

Read as bytes. Write as bytes.

Don't use BufferedReader or InputStreamReader.

Use BufferedInputStream instead.


A second problem is that you need to call response.setContentType("image/png") before you call response.getOutputStream(). Calling getOutputStream() orgetWriter()` "commits" the response by outputting the response headers. Changes to the headers (such as the content type) after the response has been committed have no effect.

How do I send an image to the output in JSP

You should start using the newer NIO.2 File API that was added in Java 7, mostly the Files class, because it makes the job much easier.

Option 1: Load file into byte[]

byte[] imageBytes = Files.readAllBytes(Paths.get("C:/test.jpeg"));

response.setContentType("image/jpeg");
response.setContentLength(imageBytes.length);
try (OutputStream out = response.getOutputStream()) {
out.write(imageBytes);
}

Option 2: Stream the file without using a lot of memory (recommended)

Path imageFile = Paths.get("C:/test.jpeg");
response.setContentType("image/jpeg");
response.setContentLength((int) Files.size(imageFile));
try (OutputStream out = response.getOutputStream()) {
Files.copy(imageFile, out);
}

Java Servlet: Write to output html text and jpg in the same response

Transfer the image base64 encoded and use data:image/...;base64 in the src attribute of the img tag.

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />

Write image file in servlet by using ImageIO

Long time ago I wrote the following code (it was taking the image stored as blob in database and writing it to the servler output):

public class ImageDB extends HttpServlet {
// ...
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ...
byte[] bytes = blob.getBytes((long)1, (int)blob.length());

ServletOutputStream out = response.getOutputStream();
out.write(bytes);
out.close(); // Close stream
// ...

}

}

Serve a static image file from the filesystem in a servlet?

Have a look over here: Example Depot: Returning an Image in a Servlet Link broken. Wayback Machine copy inserted below:

// This method is called by the servlet container to process a GET request.
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// Get the absolute path of the image
ServletContext sc = getServletContext();
String filename = sc.getRealPath("image.gif");

// Get the MIME type of the image
String mimeType = sc.getMimeType(filename);
if (mimeType == null) {
sc.log("Could not get MIME type of "+filename);
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}

// Set content type
resp.setContentType(mimeType);

// Set content size
File file = new File(filename);
resp.setContentLength((int)file.length());

// Open the file and output streams
FileInputStream in = new FileInputStream(file);
OutputStream out = resp.getOutputStream();

// Copy the contents of the file to the output stream
byte[] buf = new byte[1024];
int count = 0;
while ((count = in.read(buf)) >= 0) {
out.write(buf, 0, count);
}
in.close();
out.close();
}

Servlet Image Display

You have serious concurrency issues in your servlet. A single instance of the servlet is used to serve all the requests to this servlet. So a servlet should be stateless. But the first thing you're doing is

this._request = request;
this._response = response;

This means that if two concurrent requests are made to the servlet, you might have the first one set these two instance variables, then the second one resetting the same instance variables. The first image would thus be sent as a response to the second request, and nothing would be sent as a response to the first request. And this is only one of the strange things that could happen. You could also have exceptions and inconsistent data.

Don't store the request and response (and any other state) in instance variables. Pass them from method to method. I've not analyzed the whole code, but the only instance field that you should have in the servlet is sessionFactory field.



Related Topics



Leave a reply



Submit