Video format Files Handling in Spring MVC - spring

I am storing image and video type data in Mongo Cluster.
I am able to get the image list from chunk and able to pass the list of images to JSP.
I would like to do same for Videos also like showing the web page with list of videos. How would i do that?
Code for image handling in controller:
BufferedImage bi = ImageIO.read(imageForOutput.getInputStream());
String imageType = StringUtils.substringAfter(imageForOutput.getFilename(),".");
out = response.getOutputStream();
ImageIO.write(bi, imageType, out);
out.close();
JSP page to Handle the images:
<c:forEach items="${images}" var="image">
<img src="getImg/${image[0]}/${image[1]}" width="100" height="100" />
</c:forEach>

I got the solution.
i did like below, i am placing the code as if some one else face the same issue then they can use it.
#RequestMapping(value = "/getVideo/{fileName}/{extension}", method = RequestMethod.GET)
public void getVideo(#PathVariable("fileName") String fileName,#PathVariable("extension") String extension,
HttpServletRequest request,
HttpServletResponse response, HttpSession session)
throws IOException, ServletException {
System.out.println("<<<<i am in video loading method, video name ...."+fileName);
GridFSDBFile imageForOutput = loginDelegate.getImageBasedOnName(fileName);
//OutputStream out = null;
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename="+imageForOutput.getFilename().replace(" ", "_"));
InputStream iStream = imageForOutput.getInputStream();
IOUtils.copy(iStream, response.getOutputStream());
response.flushBuffer();

Related

How to fix displaying the same image for item of each

Question: How to fix displaying the same image for item of each ?
thymleaf.html
<div th:each="goals : ${goals}">
<div th:text="${goals.getId()}"></div>
<img th:src="#{'image/'+ ${goals.getId()}}" width="100px;"
height="100px;"/>
<div th:text="${goals.title}"></div>
controller of image
#GetMapping(value = "/image/{id}")
public void showProductImage(#PathVariable String id,
HttpServletResponse response) throws IOException{
Goals goals = goalsRepository.findById(UUID.fromString(id));
logger.info("I got id--"+id);
response.setContentType("image/jpeg, image/jpg, image/png,
image/gif");
response.getOutputStream().write(goals.getImage());
response.getOutputStream().close();
controller of view page
#GetMapping(value = "/goals")
public String read(Model model) {
model.addAttribute("login", new LogIn()); //it for bottom menu
model.addAttribute("currentlyPage","goals"); // it for top menu
model.addAttribute("addNewGoal", new addNewGoal()); //another page
//get all goals
List<Goals> goals = new ArrayList<>();
goalsRepository.findAll().forEach(goals::add);
model.addAttribute("goals",goals);
return "goals";
log4j
I got id--bc8c9820-9500-
I got id--5ba1d0d0-9504-
I got id--bff1d8a0-94ff-
I got id--1f0da4f0-94ff-11e9-970f-0bfed788288d
I got id--d76dd9b0-9500-11e9-81ae-c9c1d3b67a0f
I got id--4aaaac80-9512-11e9-b98b-7deb4e16d250
I got id--608dae20-94ff-11e9-89b4-83a8b92aa5c9
I expect different images, but everywhere same images.enter image description here
I found the solution.
I changed image type of entity to ByteBuffer
I changed controller by next code:
#GetMapping(value = "/image/{id:.+}")
public #ResponseBody ResponseEntity<byte[]> showProductImage(#PathVariable String id, HttpServletResponse response) throws IOException {
Goals goals = goalsRepository.findById(UUID.fromString(id));
ByteBuffer buffer =goals.getImage();
byte[] bytes = buffer.array();
return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(bytes);
}
I changed some valueOf type for converting .

Spring response entity image

I wrote a rest controller to return an image associated with a primary key. Now I wanted to load this image in the browser and I am running into issues:
(1) If I type a GET URL to the image the browser (FireFox and Chrome) don't display the image but they are seeing all the headers properly. Additionally firefox says "The image cannot be displayed because it contains errors"
(2) If I used XMLHttpRequest to create get the image using the URL I get the image but it displays only partially (the bottom half is cut off and is set to transparent).
#GetMapping("/{featureId}/loadImage")
public ResponseEntity<byte []> loadImageForId(#PathVariable long featureId, HttpServletResponse response) throws IOException {
log.info("Getting image for feature id " + featureId);
Feature feature = featureService.getFeatureById(featureId);
File file = featureService.loadImageForFeature(feature);
byte [] imageData = new byte[(int) file.length()];
FileInputStream inputStream = new FileInputStream(file);
inputStream.read(imageData);
inputStream.close();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(...));
headers.setContentLength(file.length());
response.setHeader("Content-Disposition", "inline; filename=" + file.getName());
return new ResponseEntity<byte[]>(imageData, headers, HttpStatus.OK);
}
if it is working on tomcat, you can use this tomcat's utility class :
import org.apache.tomcat.util.http.fileupload.IOUtils
for example:
response.setContentType("image/jpeg");
InputStream is = new ByteArrayInputStream(imageByteArray);
IOUtils.copy(is,response.getOutputStream());
Okay finally after hours of debugging with curl etc, I was able to verify that the response body was not getting properly encoded image (nothing to do with the headers).
This was caused due to the choice of InputStream and OutputStream objects.
Instead of using FileInputStream I switched to using ImageIO and the underlying BufferedImage to write the output to the ServletResponse as follows:
#GetMapping("/{featureId}/loadImage")
public void loadImageForId(#PathVariable long featureId, HttpServletResponse response) throws IOException {
log.info("Getting image for feature id " + featureId);
Feature feature = featureService.getFeatureById(featureId);
File imageFile = featureService.loadImageForFeature(feature);
MediaType mediaType = MediaType.parseMediaType(Files.probeContentType(imageFile.toPath()));
response.setHeader("Content-Disposition", "inline; filename=" + imageFile.getName());
response.setStatus(HttpStatus.OK.value());
response.setContentType(mediaType.toString());
response.setContentLength((int)imageFile.length());
OutputStream os = response.getOutputStream();
ImageIO.write(ImageIO.read(imageFile), mediaType.getSubtype(), os);
os.flush();
os.close();
}

loading dynamic image from local source

I have saved some images to local path of pc and saved the file name to db. Now i want to load all the image from db and show to html page using java script and thymemleaf. Browser says not allowed to load local resources , So i made a servlet in spring boot. But it does not showing image.
Servlet
#WebServlet("/admin/imgServlet")
public class AdminImageServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String urlImage = request.getParameter("admin");
response.setContentType("image/jpeg");
ServletOutputStream out;
out = response.getOutputStream();
FileInputStream fin = new FileInputStream("C:/Users/Public/Documents/" + urlImage);
BufferedInputStream bin = new BufferedInputStream(fin);
BufferedOutputStream bout = new BufferedOutputStream(out);
int ch = 0;
while ((ch = bin.read()) != -1) {
bout.write(ch);
}
bin.close();
fin.close();
bout.close();
out.close();
}
}
#Bean
public ServletRegistrationBean adminImageServlet() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(AdminImageServlet.class);
dispatcherServlet.setApplicationContext(applicationContext);
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/admin/imgServlet");
servletRegistrationBean.setName("imgServlet");
return servletRegistrationBean;
}
Java script for loading image
'<img src=imgServlet?admin='+articles.bannerImg+' class="img-responsive" />'
error i'm getting imgServlet:1 GET http://localhost/techtalks/admin/imgServlet?admin=pyjc4x0B.jpeg 404 (Not Found)
And i also want to load image from local resources to thymeleaf html page
model.addAttribute("localImg", "E:\\picz\\assasins.jpg"); spring controller will pass the Model like this and it will pass the image to respective file to html page like this.
<img th:src="#{${localImg}}"/>
Your Servlet code works for me. I am able to get the image successfully.
I presume the problem could be most likely the file name. Please input the file name as below (i.e. without 'e' in jpeg).
It should work if the file is present in the local path that you are referring.
pyjc4x0B.jpg

Spring returning image as ResponseEntity<byte[]> - image corrupt

I am working on a spring 3.2.7 app and it sends signatures stored in the database as base64 string back to the users browser via a spring controller which outputs the byte array ResponseEntity.
The image is always corrupted and I havent worked on this part of the system as I double checked in svn and the controller has not been touched since the branch I am working on was created.
I am able to convert the base64 string to an image on my desktop and I am also able to the convert the byte array returned to browser into an image before spring steps in.
Below is my code, this was apparently working before so perhaps there is some config change that could cause this?
#RequestMapping(value = "/submissions/signature/{type}/{id}", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<byte[]> getSignature(#PathVariable String type, #PathVariable Integer id) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String base64 = ... gets from db
byte[] bytes = Base64.decodeBase64(base64);
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(bytes));
ImageIO.write(bi, "png", baos);
HttpHeaders headers = new HttpHeaders();
headers.setLastModified(Calendar.getInstance().getTime().getTime());
headers.setCacheControl("no-cache");
headers.setContentType(MediaType.IMAGE_PNG);
headers.setContentLength(baos.toByteArray().length);
//Image as base64 string is ok in converter
System.out.println("BASE 64 IMAGE IS: " + base64);
//This image is created ok on desktop
FileOutputStream fos = new FileOutputStream("C:\\Users\\p\\Desktop\\test_signature.png");
fos.write(bytes);
fos.close();
//This image is created ok on desktop
FileOutputStream fos3 = new FileOutputStream("C:\\Users\\p\\Desktop\\test_signature_baos.png");
fos3.write(bytes);
fos3.close();
return new ResponseEntity<byte[]>(baos.toByteArray(), headers, HttpStatus.OK);
}
The image is being rendered in the browser like:
<img id="userSignature" width="296" height="110" style="border:0px" src="/webapp/service/submissions/signature/user/${subid}" alt="User signature" />
I have not changed this class and I am told that it did work, I am able to create images from both byte arrays and they are ok and looks the same and I able to render the signature string ok for testing like:
<IMG SRC="data:image/png;base64, <base_64_string>" ALT="">
has anyone experienced similar issues or know what could be causing this?
I have now tried sending an image from my file system already created as png and that also fails.
I have now noticed that CSV files do not download properly in the app and they stream in the same way:
#RequestMapping(value = "/results/csv", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<byte[]> getResultsInCsvFormat() throws IOException {
I have successfully returned file contents with the help of an InputStream:
#RequestMapping(value = "/submissions/signature/{type}/{id}",
method = RequestMethod.GET)
public HttpEntity getFile(HttpServletResponse response,
#PathVariable String type,
#PathVariable Integer id) {
String base64 = "foo"; // get base-64 encoded string from db
byte[] bytes = Base64.decodeBase64(base64);
try (InputStream inputStream = new ByteArrayInputStream(bytes)) {
StreamUtils.copy(inputStream, response.getOutputStream());
response.setContentType(MediaType.IMAGE_PNG_VALUE);
} catch (IOException e) {
// handle
}
return new ResponseEntity(HttpStatus.OK);
}
Note that I'm not using ResponseBody, and in my working version I am using MediaType.APPLICATION_OCTET_STREAM_VALUE rather than the actual file content type.
The accepted solution didn't work for me in Spring Boot 2.x for Base64 images. Here is how I returned a Base64 image:
#GetMapping(value = "/pixels/{id}", produces = MediaType.IMAGE_PNG_VALUE)
#ResponseBody
public byte[] pixelTracking(#PathVariable String id) {
// TODO: do whatever you want here
// return png image
String base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=";
return Base64.getDecoder().decode(base64);
}
Ok so I have fixed this now with some thanks to beerbajay who showed me that downloading by streaming to the response directly was ok and also that I should look at ByteArrayHttpMessageConverter.
It turned out that I had made a mistake in the spring config and I realised this after reading the spring documentation that told me that ByteArrayHttpMessageConverter is registered automatically when using <mvc:annotation-driven />.
The mvc annotation driven tag had been removed from the config as I thought this was doing the same thing (and I thought it only needed to be declared once within a spring context):
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
It looks like this alone isnt sufficient to set up annotation-driven in the app and I have added back in the tag to the context.xml file.
I dont understand why this needs to be in two places though as all the xml config is loaded through same xml file in what I assumed was the same spring context:
<import resource="config/properties.xml" />
<import resource="config/security.xml" />
<import resource="config/context.xml" />
<import resource="config/content-negotiation.xml" />
<import resource="config/rest-client.xml" />
my solution is :
backend is spring boot and frontend is reactjs
bug is different syntax is backend and frontend : java use ("_","-") and web(reactjs,...) use ("/","+") |
for example : "PGjQOA66-_ne-" convert to "PGjQOA66+//ne/+"
you can testing base64 in this link :https://onlinepngtools.com/convert-base64-to-png
back end code :
ByteArrayOutputStream baos = new ByteArrayOutputStream();
File file = new File(path);/// path : is external directory and local directory in server
FileInputStream imageInFile = new FileInputStream(path);
byte imageData[] = new byte[(int) file.length()];
imageInFile.read(imageData);
String base64 = encodeImage(imageData);
/// 1. Not show if size up 300KB !!! :|
/// 2. base64.replaceAll("_","/").replaceAll("-","+")
byte[] bytes = Base64.decodeBase64(base64.replaceAll("_","/").replaceAll("-","+"));
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(bytes));
ImageIO.write(bi, "png", baos);
HttpHeaders headers = new HttpHeaders();
headers.setLastModified(Calendar.getInstance().getTime().getTime());
headers.setCacheControl("no-cache");
headers.setContentType(MediaType.IMAGE_PNG);
headers.setContentLength(baos.toByteArray().length);
return new ResponseEntity<byte[]>(baos.toByteArray(), headers, HttpStatus.OK);
and other solution for back end:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
File file = new File(path);/// path : is external directory file and local directory file in server, or path get of database.
FileInputStream imageInFile = new FileInputStream(path);
byte imageData[] = new byte[(int) file.length()];
imageInFile.read(imageData);
/// 1. Not show if size up 300KB !!! :| i dont now!
/// 2. base64.replaceAll("_","/").replaceAll("-","+")
String base64 = encodeImage(imageData).replaceAll("_","/").replaceAll("-","+");
return base64;
and reactjs code is :
const [imageData, setImageData] = React.useState({});
setImageData(...request to backend);
<img src={`data:image/png;base64,${imageData}`} alt="This Is alert" />

SPRING MVC 3 - NOT displaying image in JSP

I have a controller serving images from an external directory (say c:\images\userID\photo.png), and this controller does its job very well. However, the img tag in my JSP file shows the image icon instead of the image returned by this controller.
Here's my controller:
#RequestMapping(value = "/load/{imageId}/", method = RequestMethod.GET)
public ResponseEntity<byte[]> loadImage(#PathVariable("imageId") Long imageId, HttpServletRequest request)
{
final org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
BufferedImage image;
Photo photo = photoManager.getSinglePhoto(imageId);
headers.setContentType(MediaType.IMAGE_PNG);
try
{
if (photo == null)
{
File defaultFile = new File("c:/images/default.png");
image = ImageIO.read(defaultFile);
return new ResponseEntity<byte[]>(((DataBufferByte)image.getData().getDataBuffer()).getData(), headers, HttpStatus.CREATED);
}
File file = new File(photo.getPath());
image = ImageIO.read(file);
return new ResponseEntity<byte[]>(((DataBufferByte)image.getData().getDataBuffer()).getData(), headers, HttpStatus.CREATED);
}
catch (IOException ex)
{
return new ResponseEntity<byte[]>(null, headers, HttpStatus.NOT_FOUND);
}
}
I have found reading other answers here, that I need to include messageConverters in my application context, and I did it.
Here's a portion of my application-context.xml
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<util:list>
<bean id="byteArrayMessageConverter" class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
</util:list>
</property>
</bean>
The eclipse XML editor complains about MethodHandlerAdapter being deprecated.
JSP:
<img src="/mavenspringapp/photo/load/131/" width="128" height="128" alt="laf02.jpg">
Why isn't the image getting displayed even when the controller sends the response correctly (201). Thanks in advance.
A little bit of googling tells me that HTTP 201 means created.
If the image exists, why are you sending a response code telling the client you just created the image?
I don't know for sure how web browsers handle it, but perhaps try changing your response codes to 200, as you aren't really creating anything.
The problem was in the controller method. Apparently loading the image the way I did it, is not correctly done. So I modified my method as shown below:
#RequestMapping(value = "/load/{imageId}/", method = RequestMethod.GET)
public ResponseEntity<byte[]> loadImage(#PathVariable("imageId") Long imageId, HttpServletRequest request)
{
final org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
Photo photo = photoManager.getSinglePhoto(imageId);
headers.setContentType(MediaType.IMAGE_PNG);
try
{
if (photo == null)
{
File defaultFile = new File("c:/images/default.png");
byte[] content = FileUtils.readFileToByteArray(defaultFile);
return new ResponseEntity<byte[]>(content, headers, HttpStatus.OK);
}
File file = new File(photo.getPath());
byte[] content = FileUtils.readFileToByteArray(file);
return new ResponseEntity<byte[]>(content, headers, HttpStatus.OK);
}
catch (IOException ex)
{
return new ResponseEntity<byte[]>(null, headers, HttpStatus.NOT_FOUND);
}
}
And now it works great! I hope this helps somebody else. Thank you all for your replies.
You may consider the alternative instead of controller displaying the images you can directly access images your jsp for this you need to put the the mapping information in your spring configuration xml like
<mvc:resources mapping="/image/**" location="file:///D:/images/" /> and in your jsp file you can directly can directly call
<img src="<spring:url value='/images/logo.png'/>" /> and make sure your have mentioned the spring tag in your jsp
<%#taglib uri="http://www.springframework.org/tags" prefix="spring"%>

Resources