Accessing images from remote or external resource in jsp - image

I am trying to implement a web page where images location is outside my web application.
I will iterate through the images folder and then load the images in jsp.
But when i do it everything works fine but images are not displaying.
I found the reason too, its prepends application context to image location.
For example if my image location is "d:/images", when the img src is resolves, the path becomes http: // hostname //portnumber/exampled/d:/images/image1.gif
Following is my code.
Service class:
public List<String> getSiteKeyImages(){
List<String> imageList = new ArrayList<String>();
File directory = new File(PropertyFileReader.getNycbMessage().getProperty("imageURL"));
if(directory.isDirectory()){
String[] images = directory.list();
for(String image:images){
imageList.add(image);
}
}
return imageList;
}
servlet class:
private List<String> images = new ArrayList<String>();
images = userService.getSiteKeyImages();
session.setAttribute("images",images);
Then my jsp page code is
<div id = "pamImages">
<ul class="thumbs noscript">
<c:forEach items="${images}" var="image">
<li>
<a id="${image}" class="thumb" name="leaf" href="javascript: selected_image('${image}')">
<img src="${CONFIG_URL}${image}" height="50" width="50"></td>
</a>
</li>
</c:forEach>
</ul>
</div>
Ca anyone tell me what wrong i am doing here.

Related

Images don't appear in ASP.NET Core 6 MVC

I'm trying to view images in an ASP.NET Core 6 MVC application but it doesn't work.
This is my controller function to add an item with image
public IActionResult Add(ProductEditViewModel model, string? returnUrl = null)
{
string? UploadUrl = "/wwwroot/Uploads/Product/";
string newFileName = Guid.NewGuid().ToString() + model.Image.FileName;
model.ImageUrl = UploadUrl + newFileName;
FileStream fs = new FileStream(Path.Combine
(
Directory.GetCurrentDirectory(),
"wwwroot",
"Uploads", "Product", newFileName
), FileMode.Create);
model.Image.CopyTo(fs);
fs.Position = 0;
ProductRepo.Add(model);
UnitOfWork.Save();
return RedirectToAction("Get");
}
I want to view it in a table, here is my <td> in the view:
<td>
<img src="#V.ImageUrl" style="width:100px; height:100px;">
</td>
#V is a ProductViewModel type.
What is the problem? I don't even know where to trace.
When you want to show image saved in wwwroot folder, You can't write url like wwwroot/.../..., browser will not find this path. You just need to write the project structure as url without wwwroot.
For example, My project structure is as follows:
wwwroot
-css
-js
-lib
-image
--Test.jpg
If I wanna show Test.jpg in the page, The correct Url is <img src="/image/Test.jpg" /> instead of <img src="/wwwroot/image/Test.jpg" />.
Note: When you want to Serve files outside of web root, You also need to configure the Static File Middleware.

Add cid image in thymeleaf template

I have the following code :
Context context = getContext(transaction.getQuoteId(),transaction);
body = templateEngine.process("....html", context);
MimeMessage mail = javaMailSender.createMimeMessage();
FileSystemResource logo = new FileSystemResource(new File("/images/logo.png"));
MimeMessageHelper helper = new MimeMessageHelper(mail, true);
helper.addInline("logo", logo);
helper.setFrom(fromEmail);
helper.setTo("...);
helper.setSubject("....");
helper.setText(body, true);
javaMailSender.send(mail);
In html code I have:
<td align="center" style="line-height: 0px; text-align:start;">
<img style="display:block; line-height:0px;margin-left: 30px;" src="cid:${logo}" width="200" alt="logo">
</td>
I also tried using th:src="'cid:logo'" but it didn't work. When I receive an email the image in not rendered.
The image resides inside :
src/main/resources/images/logo.png
I also allowed access to "/images/.., /resources/.." in HttpSecurity ant matchers.

Spring, Thymleaf and lists of strings

Okay, I a wet-behind-the-ears newcomer to Spring and Thymleaf. I'm trying to do something so simple it should be a no-brainer. But I can't get it to work. The simple question is - how do you show a list of strings in an web page?
I have the following model
import java.util.List;
public class TestModel {
private List<String> list = null;
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public List<String> getList() { return list; }
public void setList(final List<String> list) {
this.list = list;
}
}
My web page contains the following:
<div th:if="${greeting.list != null}">
<h1>Result</h1>
<ul>
<th:block th:object="${greeting}" th:each="item : ${list}">
<li th:text="${item.name}">Item description here...</li>
</th:block>
</ul>
</div>
I added the ".name" to "item" only because I found a couple of examples where they had a list of strings and did something similar. But they had the ".name" on the object.
But it still doesn't work. The unordered list ends up empty. I.e. There isn't any list items inside the unordered tags.
What am I doing wrong? Pointers gladly accepted.
Since there's no example of filling model I supposed you put some strings into instance of TestModel's list field like this.
TestModel greeting= new TestModel();
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
model.addAttribute("greeting", greeting);
Then there are more errors in your Thymeleaf template example.
If you are using object selection through th:object you must at first place use asterix * to access object properties. Asterisk syntax evaluates expressions on selected objects instead of context variables map.
Object selection affects only children nodes in DOM.
In your example you want iterate over list of strings (List<String>) but you want to access property name which in fact don't exists on Java String object.
You must fix your Thymeleaf template in one way - see examples.
No object selection at all
<div th:if="${greeting.list != null}">
<h1>Result</h1>
<ul>
<li th:each="item : ${greeting.list}" th:text="${item}">Item description here...</li>
</ul>
</div>
Proper object selection
<div th:if="${greeting.list != null}">
<h1>Result</h1>
<ul>
<th:block th:object="${greeting}">
<li th:each="item : *{list}" th:text="${item}">Item description here...</li>
</th:block>
</ul>
</div>
<table th:object="${userList}" id="userTable" border="1">
<tr th:each="user :${userList}">
<td th:text="${user.getName()}"></td>
<td th:text="${user.getEmail()}"></td>
</tr>
</table>
Another example using table and Object. Might be useful to someone else.
In thymeleaf, if you are looking to create in a template a list of strings and compare it with a string, you can use the following structure.
th:if="${#lists.contains({'RO', 'UK', 'DE', 'BE'}, #session.getAttribute('country'))}"

Spring MVC 3.2 Thymeleaf Ajax Fragments

I'm building application with Spring MVC 3.2 and Thymeleaf templating engine. I'm a beginner in Thymeleaf.
I have everything working, including Thymeleaf but I was wondering if anyone knows of a simple and clear toturial on how to do simple Ajax request to controller and in result rendering only a part of a template (fragment).
My app has everything configured (Spring 3.2, spring-security, thymeleaf, ...) and works as expected. Now I would like to do Ajax request (pretty simple with jQuery but I don't wan't to use is since Thymeleaf in its tutorial, chapter 11: Rendering Template Fragments (link) mentiones it can be done with fragments.
Currently I have in my Controller
#RequestMapping("/dimensionMenuList")
public String showDimensionMenuList(Model model) {
Collection<ArticleDimensionVO> articleDimensions;
try {
articleDimensions = articleService.getArticleDimension(ArticleTypeVO.ARTICLE_TYPE);
} catch (DataAccessException e) {
// TODO: return ERROR
throw new RuntimeException();
}
model.addAttribute("dimensions", articleDimensions);
return "/admin/index :: dimensionMenuList";
}
the part of the view where I would like to replace <ul></ul> menu items:
<ul th:fragment="dimensionMenuList" class="dropdown-menu">
<li th:unless="${#lists.isEmpty(dimensions)}" th:each="dimension : ${dimensions}">
</li>
</ul>
Any clue is greatly appreciated. Especially if I don't have to include any more frameworks. It's already too much for java web app as it is.
Here is an approach I came across in a blog post:
I didn't want to use those frameworks so in this section I'm using jQuery to send an AJAX request to the server, wait for the response and partially update the view (fragment rendering).
The Form
<form>
<span class="subtitle">Guest list form</span>
<div class="listBlock">
<div class="search-block">
<input type="text" id="searchSurname" name="searchSurname"/>
<br />
<label for="searchSurname" th:text="#{search.label}">Search label:</label>
<button id="searchButton" name="searchButton" onclick="retrieveGuests()" type="button"
th:text="#{search.button}">Search button</button>
</div>
<!-- Results block -->
<div id="resultsBlock">
</div>
</div>
</form>
This form contains an input text with a search string (searchSurname) that will be sent to the server. There's also a region (resultsBlock div) which will be updated with the response received from the server.
When the user clicks the button, the retrieveGuests() function will be invoked.
function retrieveGuests() {
var url = '/th-spring-integration/spring/guests';
if ($('#searchSurname').val() != '') {
url = url + '/' + $('#searchSurname').val();
}
$("#resultsBlock").load(url);
}
The jQuery load function makes a request to the server at the specified url and places the returned HTML into the specified element (resultsBlock div).
If the user enters a search string, it will search for all guests with the specified surname. Otherwise, it will return the complete guest list. These two requests will reach the following controller request mappings:
#RequestMapping(value = "/guests/{surname}", method = RequestMethod.GET)
public String showGuestList(Model model, #PathVariable("surname") String surname) {
model.addAttribute("guests", hotelService.getGuestsList(surname));
return "results :: resultsList";
}
#RequestMapping(value = "/guests", method = RequestMethod.GET)
public String showGuestList(Model model) {
model.addAttribute("guests", hotelService.getGuestsList());
return "results :: resultsList";
}
Since Spring is integrated with Thymeleaf, it will now be able to return fragments of HTML. In the above example, the return string "results :: resultsList" is referring to a fragment named resultsList which is located in the results page. Let's take a look at this results page:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
</head>
<body>
<div th:fragment="resultsList" th:unless="${#lists.isEmpty(guests)}" id="results-block">
<table>
<thead>
<tr>
<th th:text="#{results.guest.id}">Id</th>
<th th:text="#{results.guest.surname}">Surname</th>
<th th:text="#{results.guest.name}">Name</th>
<th th:text="#{results.guest.country}">Country</th>
</tr>
</thead>
<tbody>
<tr th:each="guest : ${guests}">
<td th:text="${guest.id}">id</td>
<td th:text="${guest.surname}">surname</td>
<td th:text="${guest.name}">name</td>
<td th:text="${guest.country}">country</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
The fragment, which is a table with registered guests, will be inserted in the results block.
Rendering only Thymeleaf fragments also works well with ModelAndView.
Your controller
#RequestMapping(value = "/feeds", method = RequestMethod.GET)
public ModelAndView getFeeds() {
LOGGER.debug("Feeds method called..");
return new ModelAndView("feeds :: resultsList");
}
Your view
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head></head>
<body>
<div th:fragment="resultsList" id="results-block">
<div>A test fragment</div>
<div>A test fragment</div>
</div>
</body>
</html>
What's actually rendered
<div id="results-block">
<div>A test fragment</div>
<div>A test fragment
</div>
</div>
As an alternate version to Sohail's great answer, I want to give a version that using javascript can send the whole th:object to the controller, integrating Thymeleaf in your forms, not having to use #PathVariable which becomes messy or not usable at all when you've forms with many fields.
For the form (using an example which returns an object which has an id and a name Strings, and feeds a combobox with a Map that has some of those objects as values) we have:
<form method="post" th:action="#{/yourMapping}" th:object="${object}" id="yourFormId">
<select th:field="*{mapOfObjects}">
<option
th:each="entry: ${mapOfObjects}"
th:value="${entry.value.id}"
th:text="${entry.value.name}" >
</option>
</select>
<p>Name:
<input type="text" th:field="*{name}" />
</p>
</form>
When this form is submited (using a button with type submit for example) the whole document will be replaced. However we can intercept this submit with javascript and do it the ajax-way. To achieve this, we will add an interceptor to our form using a function. First call the function that adds the interceptor right after the form:
<script>formInterceptor("yourFormId");</script>
And the function looks like this (place it in the head of the document or wherever suits your needs):
<script>
function formInterceptor(formName) {
var $form = $("#" + formName);
$form.on('submit', function(e) {
e.preventDefault();
$.ajax({
url : $form.attr('action'),
type : 'post',
data : $form.serialize(),
success : function(response) {
if ($(response).find('.has-error').length) {
$form.replaceWith(response);
}
else{
$("#ajaxLoadedContent").replaceWith(response);
}
}
});
});
};
</script>
Now whenever the form is submited, this function will trigger, and it will:
Prevent the original form submit
Make an ajax call using the url defined in the form's th:action
Serialize the form data. Your controller will be able to recieve this in an object
Replace the part of your html code with the returned fragment
The replaced part should look like this
<div id="ajaxLoadedContent"></div>
And the controller can recieve the th:object in the form, with it's values filled, like this (Replace Object with your object's type and "object" with a proper name):
#PostMapping(value = /yourMapping)
public String ajaxCtrlExample(#ModelAttribute("object") Object object, Model model) {
return yourFragmentPath;
}
And that's everything. Call the function that adds the interceptor after every form you need in ajax-version.

FileContentResult render in View without specific Controller Action

I have same action in a controller that fetch from db for example a Employee with a name, age, image (byte[]).
So I store the info in ViewBag. Then in the View the specific code for the image is:
<img src="#ViewBag.Image" alt="Logo" />
But when I see the content of the response I have:
<img src="System.something.FileContentResult" alt="Logo" />
I have seen a lot of examples that gets the FileContentResult from a specific Action in a Controller for example:
(The code is an example only)
public ActionResult GetEmployeeImage (int id){
byte[] byteArray = GetImageFromDB(id);
FileContentData file = new File (byteArray,"image/jpg");
return file;
}
And then render the image with:
<img src="#Url.Action("GetEmployeeImage", "Home", new { id = ViewBag.Id })" alt="Em" />
But I dont want that because I already have the image.
How can I render it to the View throw the ViewBag?
Thanks!
PD: Rendering image in a View is the same but was not concluded
One possibility is to use the data URI scheme. Bear in mind though that this will work only on browsers that support it. The idea is that you would embed the image data as base64 string into the src attribute of the img tag:
<img src="data:image/jpg;base64,#(Html.Raw(Convert.ToBase64String((byte[])ViewBag.Image)))" alt="" />
If on the other hand you want a solution that works in all browsers you will have to use a controller action to serve the image. So in the initial request fetch only the id, name and age properties of the employee and not the image. Then write a controller action that will take the employee id as parameter, query the database, fetch the corresponding image and return it as file result. Then inside the view point the src attribute of the img tag to this controller action.
Based on the answer of #darin , if any one wants to make it via calling a controller's action:
public FileContentResult GetFileByID(string ID)
{
try
{
// Get the object from the db
Ent ent = Biz.GetPatientsByID(ID);
// Convert the path to byte array (imagepath is something like: \\mysharedfolder\myimage.jpg
byte[] doc = EFile.ConvertToByteArray(ent.ImagePath);
string mimeType = File(doc, MimeMapping.GetMimeMapping(Path.GetFileName( ent.ImagePath))).ContentType;
Response.AppendHeader("Content-Disposition", "inline; filename=" + Path.GetFileName(ent.ImagePath));
return File(doc, mimeType);
}
catch (Exception ex)
{
throw ex;
}
}
In the front end:
<img id="ItemPreview" src="#Url.Action("GetFileByID","Patient", new {ID= Model.ID })" alt="" width="350" height="350" />
Where Patient is the controller name.

Resources