Reputation: 23
I need to get an image from MongoDB GridFS system, then displaying it in a JSP img tag. This is my code that isnt working:
@RequestMapping(value = "/getPhoto", method = RequestMethod.GET)
public @ResponseBody
void getPhoto(HttpServletRequest request,
HttpServletResponse response) {
try {
System.out.println("getting photo...");
GridFSDBFile imageForOutput = userFacade.loadProfilePhoto((User) SecurityContextHolder.getContext().getAuthentication()
.getPrincipal());
BufferedImage image = ImageIO.read(imageForOutput.getInputStream());
byte[] imageBytes = ((DataBufferByte) image.getData().getDataBuffer()).getData();
response.setHeader("expires", "0");
response.setContentType("image/jpg");
response.setContentLength(imageBytes.length);
OutputStream out = response.getOutputStream();
out.write(imageBytes, 0, imageBytes.length);
out.flush();
out.close();
return;
} catch (Exception e) {
// TODO Auto-generated catch block
}
Firstly i get the GridFSDBFile and then I need to get the byte[].After that i write it in the response object but i dont know if i am doing it correctly.
The code in the JSP is as follows:
<c:url var="getPhoto" value="/settingsAdmin/getPhoto" />
<div id="preview">
<img id="imagePreview" src="${getPhoto}" alt="Profile Photo"/>
</div>
Finally, the controller is called correctly but the mistake must be inside it.
Thx in advance
Upvotes: 1
Views: 2888
Reputation: 3748
try this,
@Controller
public class GetImageController {
private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.
@Autowired
ServletContext servletContext;
@RequestMapping(value="/getImage", method=RequestMethod.GET)
public void getPhoto(HttpServletRequest request,
HttpServletResponse response) {
try {
System.out.println("getting photo...");
File image = new File("E:\\path\\to\\image.jpg");
System.out.println("file exists: "+image.exists());
// Get content type by filename.
String contentType = servletContext.getMimeType(image.getName());
// Init servlet response.
response.reset();
response.setBufferSize(DEFAULT_BUFFER_SIZE);
response.setContentType(contentType);
response.setHeader("Content-Length", String.valueOf(image.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + image.getName() + "\"");
// Prepare streams.
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
// Open streams.
input = new BufferedInputStream(new FileInputStream(image), DEFAULT_BUFFER_SIZE);
output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
// Write file contents to response.
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
} finally {
// Gently close streams.
close(output);
close(input);
}
// Check if file is actually an image (avoid download of other files by hackers!).
// For all content types, see: http://www.w3schools.com/media/media_mimeref.asp
if (contentType == null || !contentType.startsWith("image")) {
// Do your thing if the file appears not being a real image.
// Throw an exception, or send 404, or show default/warning image, or just ignore it.
response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
return;
}
}
// Helpers (can be refactored to public utility class) ----------------------------------------
private static void close(Closeable resource) {
if (resource != null) {
try {
resource.close();
} catch (IOException e) {
// Do your thing with the exception. Print it, log it or mail it.
e.printStackTrace();
}
}
}
}
and in jsp render image like:
<c:url value="/getImage" var="imgUrl"/>
<img alt="my image" src="${imgUrl}"> //to display on browser
<a href="${imgUrl}">img</a> //to display in new window
Note: This is not better way to display images in spring MVC, But in Servlets
Other way is(two lines of code):
return direct byte[]
and specify produces = MediaType.IMAGE_JPEG_VALUE
in @RequestMapping
like:
@RequestMapping(value="/getImage", method=RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
public @ResponseBody byte[] getPhoto() throws IOException {
System.out.println("getting photo...");
FileInputStream image = new FileInputStream(new File("E:\\path\\to\\image.jpg"));
return IOUtils.toByteArray(image);
}
Both way's are worked fine for me.
Upvotes: 0
Reputation: 23
Finally i reached a solution by myself, i post it so others can work it out:
The Controller part
@RequestMapping(value = "/getPhoto", method = RequestMethod.GET)
public @ResponseBody
void getPhoto(HttpServletRequest request,
HttpServletResponse response) {
try {
GridFSDBFile imageForOutput = userFacade.loadProfilePhoto((User) SecurityContextHolder.getContext().getAuthentication()
.getPrincipal());
InputStream is = imageForOutput.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
byte[]imagenEnBytes = buffer.toByteArray();
response.setHeader("Accept-ranges","bytes");
response.setContentType( "image/jpeg" );
response.setContentLength(imagenEnBytes.length);
response.setHeader("Expires","0");
response.setHeader("Cache-Control","must-revalidate, post-check=0, pre-check=0");
response.setHeader("Content-Description","File Transfer");
response.setHeader("Content-Transfer-Encoding:","binary");
OutputStream out = response.getOutputStream();
out.write( imagenEnBytes );
out.flush();
out.close();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
The JSP view
<c:url var="getPhoto" value="/settingsAdmin/getPhoto" />
<div id="preview">
<img id="imagePreview" src="${getPhoto}"alt="Profile Photo"/>
</div>
Thank you everyone for your help
Upvotes: 1