How I do get an image blob from JSP to JavaScript? - java

I retrieved a blob along with some other data from a table, say name and image:
name = varchar, image = blob
I set this to an object in my filter and pass it to the JSP file:
request.setAttribute("info", object);
In the JSP file I get that data:
request.getAttribute("info");
Now that I have the data from that object how do I go about passing that info to my JS file and render the image as a source for the JS file?
I'm trying:
<div>
<script type="text/javascript" src="jsFile.js></script>
</div>
var name = <%=info.name%>;
var image = <%=info.image%>
It just doesn't seem to be working. What is the correct method of doing this?

This isn't going to work. Leave the blob there in the server side. JavaScript on the client side can't do anything sensible with binary data. All it needs is an URL of the image so that it can reference it in the src attribute of a HTML <img> element, so that the webbrowser can in turn do its job of downloading and displaying the image. Best would be to include the image identifier in the URL. The name is unique for the image, right? Use that in the URL instead.
The first step is to let JS create a HTML <img> element with the proper src attribute which points to an URL which returns the image. Assuming that you're preparing the data like follows
String name = "foo.png";
String imageURL = "imageservlet/" + name;
request.setAttribute("imageURL", imageURL);
and are printing it in JSP(!) as if it are JS variables as follows
<script>
var imageURL = '${imageURL}';
// ...
</script>
(please note that those singlequotes are thus mandatory to represent them as a JS string variable)
so that they end up in the generated HTML source like follows (rightclick page in browser and do View Source to verify it)
<script>
var imageURL = 'imageservlet/foo.png';
// ...
</script>
then you can create the image as follows
var img = document.createElement("img"); // or getElementById("someId")?
img.src = imageURL;
// ... add to document?
(please note that this is just an example, I have no utter idea what the functional requirement is and what you would like to do with this image element, even more, perhaps JS code isn't needed at all for the concrete functional requirement)
so that it ends up like this in HTML:
<img src="imageservlet/foo.png" />
Now, the second step is to create a servlet which listens on an URL pattern of /imageservlet/*, retrieves the image as an InputStream from the database by the passed-in indentifier and writes it to the OutputStream of the response along a set of correct response headers. Long story short, I've posted several answers before as to how to do it, they contains kickoff code snippets:
How to retrieve and display images from a database in a JSP page?
Writing image to servlet response with best performance

You can access your data from the script if you set the variables in a script block before your jsFile.js. Ie:
<div>
<script type="text/javascript">
var name = <%=info.name%>;
var image = <%=info.image%>;
</script>
<script type="text/javascript" src="jsFile.js></script>
</div>
I'm not sure how you intend to handle the binary (BLOB) image data however? Typically this would be written to an image file on the server and referenced via an img tag:
<img src="/path/to/myimage.jpg" />
Instead of passing your blob data to the JSP file, I would suggest having the server (your servlet) pass a URL to the JSP which the browser can use to get the image via an img tag. You can either write the blob data to a URL or write a servlet that writes out Content-type: image/jpeg (or similar) data when passed an id, ie:
<img src="http://www.yourserver.com/GetImage?imageId=xxx" />

Related

How can you build an absolute URL in thymeleaf?

I would like to display an absolute url generated at run-time with a parameter. Not create a href to a page but display the URL using th:text. Any simple way to do this with Tymeleaf (without having to concatenate the URL pieces from #request object and without using some MVC utility class)?
Attempt 1
<p th:text="#{/myServlet(myParam=${dynamicParameter})}" /> - only displays part of the URL leaving out the protocol, port and host name. I am getting /myServlet?myParam=123. The same behavior as for th:href, if you inspect the <a> you will see the same href - in that case the browser helps by inferring the protocol, port and so on
Attempt 2
th:text="#{__${#httpServletRequest.requestURI}__}" - produces a relative URI of the current page that doesn't include the protocol and so on
Attempt 3
th:text="#{__${#httpServletRequest.requestURL}__}" - produces this time an absolute URL of the current page containing the protocol, host and servlet context. The problem now is when I display this text from a different page, my URL is ...myApp/myOtherServlet so I need to edit this string to replace myOtherServlet with the URI I want.
Non Tymeleaf Attempt 1
#Service("urlUtils")
public class UrlUtilsServiceImpl implements UrlUtilsService {
#Override
public String getAbsoluteUrlTo(final String aPath, final String param, final String value){
return ServletUriComponentsBuilder
.fromCurrentContextPath()
.path(aPath)
.queryParam(param, value)
.build().toString();
}
}
page.html:
th:text="${#urlUtils.getAbsoluteUrlTo('/myServlet', 'myParam', ${dynamicParameter})}"
The problem is the host name that can be aliased before it reaches my server (see this).
Thymeleaf+JS Sollution
Using some java script plus thymeleaf
<p id="myUrl" th:text="#{/myServlet(myParam=${dynamicParameter})}" />
<script type="text/javascript">
$(document).ready(function () {
var myUrl= $("#myUrl");
myUrl.text(window.location.origin + myUrl.text());
});
</script>
You can concatenate servlet request on the fly:
th:text="${#httpServletRequest.scheme}+'://'+${#httpServletRequest.serverName}+':'+${#httpServletRequest.serverPort}+#{/myServlet(myParam=${dynamicParameter})}"
Or for JavaScript:
<script type="text/javascript">
GLOBAL.serverURI = '[[${#httpServletRequest.scheme}+'://'+${#httpServletRequest.serverName}+':'+${#httpServletRequest.serverPort}+#{/myServlet(myParam=${dynamicParameter})}]]';
</script>

Grails get url of originating controller

I have a URL say abc.com/somecontroller?someparam=1 which renders a form. Form on submit sends the form params to /ajaxAction
Is there a way I could get this abc.com/somecontroller?someparam=1 (i.e. the form URL?)
I am more interested in getting the someparam value from the URL of the form.
PS: the above URL abc.com/somecontroller?someparam=1 is dynamically generated, so I can not access it otherwise.
And request.forwardURI will give me /ajaxAction (i.e. the URL of the action in form and not the url of the form itself).
EDIT:
I have no control over form as it is also dynamic and user has hundreds of templates to select from. Each template has different no. of fields.
So if I would prefer some other way to get the URL.
Why don't you use javascript in form and add to ajax request array with GET params? (or with the url of the action which generated form)
You can get them from original request f.e. by this script.
While rendering the GSP of your form, you can do like this:
myaction.gsp
<html>
<body>
<!-- Your content -->
<script>
var paramsString = '${params.collect { k, v-> "$k=$v" }.join​​​​​​​​​​​​​​​​​​​​​​("&")​​​ }';
</script>
</body>
</html>
So, when you GSP is rendered, the script tag will have something like this (for a URL abc.com/somecontroller?someparam=1&foo=2:
var paramsString = 'someparam=1&foo=2';
Now, in your AJAX code, you can pass that string as the query arguments:
$.ajax({
url: '/ajaxAction?' + paramsString
/* rest of the AJAX code */
});
Now, in your ajax controller action, you can simply do the params.someparam.
EDIT
Well, I just realized that you don't have to any GSP stuff I mentioned above. Simply do the AJAX call like this:
$.ajax({
url: '/ajaxAction' + location.search
/* rest of the AJAX code */
});
The location.search will give you the direct string: ?someparam=1&foo=2
I ended up using flash to store the someparam
In my controller which is being used to render the form at abc.com/somecontroller?someparam=1 I use flash as this:
flash.put("someparam", params.someparam)
This worked as a quick workaround to the issue. I feel this would work well in situations where I have no control over the gsp.
If anyone finds any issue, please comment otherwise I will mark this as the answer.

XSS - encode - decode a href/url

I have a usecase where I have a text input field which takes URL and saves it.
That saved url is used in a jsp file
<script type="text/javascript">
var defaultSimulatorUrl = '<%= defaultSimulatorUrl %>';
</script>
Variable defaultSimulatorUrl is used to show in prefilled text input fields
Some attacker can attack defaultSimulatorUrl's value by sending http://abcxyz.com?a=b&c=d';alert(1);//
Script content will be converted to
<script type="text/javascript">
var defaultSimulatorUrl = 'http://abcxyz.com?a=b&c=d';alert(1);//';
</script>
My problem is if I encode this Url using com.adobe.granite.xss.XSSAPI.encodeForHTML(), how can i get orignal url to show in input field
Or Can I encode it by some other means to be used in prefilled text input fields
XSSAPI does not provides api to decode string back
I used XSSAPI's encodeForJS method which solved my problem

Ajax response in datatables

I was implementing an interface with uses DataTables and excel files. Motive is upload an excel and then show it in DataTables.
As I didn't find any javascript library which parse the excel and provide it to DataTables. The only option is ot send the data to the front end struts/ java and send back the json.
Is it possible to have DataTables waiting for the json by Ajax without sending the request. .
i think, it is possible in html5 and javascript. run and test the code below.
<html>
</head>
<script>
function readBlob() {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = 0;
var stop = file.size;
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
document.getElementById('byte_content').textContent = evt.target.result;
}
};
var blob = file.slice(start, stop);
reader.readAsBinaryString(blob);
}
</script>
</head>
<body>
<input type="file" id="files" name="file" accept=".csv" />
<span class="readBytesButtons">
<button onclick="readBlob()">entire file</button>
</span>
<div id="byte_range"></div>
<div id="byte_content"></div>
</body>
</html>
we can extract the excel data as text by FileReader in javascript.
if you want to display the data in datatable, please apply your logic.
Yes off course,
I think you want to try something like this
upload file to server
read the excel file in strut action, save it on disk in temp folder and return file name to your JSP.
when first step done then make Ajax Call to struts action
pass file name as parameter fom datatable ajax call
load file from disk read it and populate in Pojo or VO object
create Json from Pojo using gosn or jakson api
finally return json.
further see data table ajax source
Yes this is possible, but no Ajax is need in your case. How would i do it? See below:
Have a form to upload the excel file to my struts implementation. Then do the processing of the excel file and return the contents in pure html/table format. Then do a simple datatables initialization on page load and your are finished!
UPDATE
For pagination, datatables support ajax like this:
var oTable = "";
$(document).ready(function() {
oTable = $('#htmltableID').dataTable({
"sPaginationType": "full_numbers",
"bServerSide": true,
"sAjaxSource": "/myAjaxSource.jsp?page="+pageNumber+",
"sServerMethod": "POST",
"iDisplayLength": 50
});
}
Then in your myAjaxSource.jsp you get the parameter page sent by the ajax URL and return the appropriate data (json)

Output HTML and images from a servlet

There are many examples on the Net of outputting images from servlets by writing to request's output buffer.
Is it possible to create an entire HTML page with multiple images in a table from a servlet?
The images would be created on the fly by a bean.
You don't want to do it that way.
I would create two servlets:
To serve an HTML page with <img src="..."> elements for each image.
To serve the binary data of the image
Basically the first servlet would send the HTML to the client browser. The browser sends new HTTP requests for each <img> element it finds. The second servlet would handle those requests by writing the image's binary data directly to the response's OutputStream.
For small images, you can embed the images using css or directly in html.
To embed using css take a look at this.
This is what I would suggest:
<html>
<body>
<img alt="some title" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA.."/>
<img alt="some title" src="data:image/png;base64<data2>"/>
<img alt="some title" src="data:image/png;base64<data2>"/>
</body>
</html
To get the exact value you should have after base64 in src attribute, you should take a look at converting png images to base64.
This solution is somewhat non-ideal and might take the page to load forever if there are more than 10-15 images in the page.
If that is the case, then you should go with the other solution of linking to the url for servlets which serve image.

Categories

Resources