Vaadin Image URL from StreamResource - image

I get my images from my database via the StreamResource and use afterwards the Image() class to show the picture. Is it possible to get from this StreamResource or Image class the URL?
Through the browser I can find out that the image has the URL that looks like: "... / Web/APP/connector/0/32/source/Picture-xxx.JPG"
I need the URL to the image for CSSInject.
Thanks in advance

So..
Client side Vaadin resource link pattern is like:
[protocol]+"://"+[currentUrl]+"/APP/connector/"+[uiId]+"/"+[cid]+"/source/"+[filename]
where:
protocol - request protocol,
currentUrl - current URL,
uiId - Vaadin UI identifier,
cid - connector identifier,
filename - filename.
Example function to get url:
String getResourceURL(AbstractClientConnector connector,FileResource resource){
String protocol = UI.getCurrent().getPage().getLocation().getScheme();
String currentUrl = UI.getCurrent().getPage().getLocation().getAuthority();
String cid = connector.getConnectorId();
Integer uiId = connector.getUI().getUIId();
String filename = resource.getFilename();
return protocol+"://"+currentUrl+"/APP/connector/"+uiId+"/"+cid+"/source/"+filename;
}
where:
connector is for example Image object
resource is FileResource

This is a typical use case for creating a request handler:
As mentioned in the provided link:
Request handlers are useful for catching request parameters or generating dynamic content, such as HTML, images, PDF, or other content.

Related

Setting link URL with Google Docs API doesn't result in update of image

I'm trying to update a placeholder image with a new image that has an updated URL. The URL in fact is a valid Google Static Map URL that I'm using in other contexts successfully. I'm using the Google Document API to manipulate the document. Following the code I've been using:
var element = body.findElement(DocumentApp.ElementType.INLINE_IMAGE).getElement();
var imageMap = element.asInlineImage();
// if there was an image found in document
if (imageMap != null) {
// get current parent and index inside parent
var parent = imageMap.getParent();
var childIndex = parent.getChildIndex(imageMap);
// remove image from paragraph
imageMap = imageMap.removeFromParent();
// get static image url for territory
var url = getStaticMapURLForTerritory(id);
Logger.log(url);
imageMap.setLinkUrl(url);
// create a new image
parent.insertInlineImage(childIndex, imageMap)
}
This seems to work fine in that it does update the image url correctly. However, the image itself (the result of the url) is not updated. When I click on the link URL it does return the correct image.
Is there a way to force a refetch of the image blob associated with the URL? I've also attempted to use UrlFetchApp but that complains about a missing size parameter (google static api) which is certainly included in the url string and within the max 640x640 bounds.
I've exhausted all my options unless....
TIA, --Paul
setLinkUrl only does that: sets the link. To actually add a new image you'll have to get its blob:
function replaceImage() {
// [...]
// get static image url for territory
const url = getStaticMapURLForTerritory(id)
const response = UrlFetchApp.fetch(url)
// create a new image
parent.insertInlineImage(childIndex, response.getBlob())
.setAltDescription(img.getAltDescription())
.setAltTitle(img.getAltTitle())
.setWidth(img.getWidth())
.setHeight(img.getHeight())
.setLinkUrl(url)
}
References
Class InlineImage (Google Apps Script reference)

Static route image showing broken (Google Maps Directions API)

I'm attempting to retrieve a static image of a route from Google Maps directions API.
// addresses
$from_address = "Mobile,AL"
$to_address = "Athens,GA"
// build static image url
$url_route_json = "https://maps.googleapis.com/maps/api/directions/json?origin=$from_address&destination=$to_address&mode=driving&key=$goog_map_dist_api_key";
// replace any spaces in the route address with + signs
$url_route_json = str_replace(' ', '+', $url_route_json);
// get the json response
$resp_json = file_get_contents($url_route_json);
// decode the json
$jsondata = json_decode($resp_json, true);
// URL encode overview_polyline
$overview_polyline = urlencode($jsondata['routes'][0]['overview_polyline']['points']);
// build image URL
$url_route_img = "https://maps.googleapis.com/maps/api/staticmap?size=600x400&path=enc%3A$overview_polyline&key=$goog_map_dist_api_key";
url_route_img becomes:
https://maps.googleapis.com/maps/api/staticmap?size=600x400&path=enc:wknnEvj%7B%7DN%7CA%60DYRgDxBZx%40hArC%60A%7CBtEtKzEfLrBhF%7E%40dD%7CGtRJ%5CrD_Bh%40K%60%40FjAbBVZJJXk%40d%40%7D%40Zm%40f%40y%40%7C%40eAtK%7BHtGoEv%40i%40HDP%40pAWvABjGn%40%7CGp%40%60F%60%40zMrAfEf%40pCf%40lEzAhCrAtMtIvBnAzB%60A%7EBt%40%7EJzBtOpDbFnAdK%60ClEz%40nOnDlCh%40bDZhDB%7CCSbCc%40j%40Oj%40N%7EEr%40jA%60%40%7E%40x%40%60LzM%60C%7CBn%40RfBN%7CBJhFj%40vD%60%40jB%5ChBbAfB%7EBpFjTpBlH%60%40%7C%40t%40%7E%40vCtBl%40j%40FXBTB%60%40iD%7EOwJdd%40%7BLxj%40sB%7CHkBvFoC%60HoC%7EFwX%7Ej%40gD%60IoCfIqCrKsBpJwNhq%40mOds%40%7DYxtAmM%60m%40iArFgBpK_BnMiCdYaFxh%40oJ%7EcAsGpr%40cC%60XsCj%5By%40bQQnIChJWnx%40e%40riB%7D%40faDIxXU%7CE%7B%40rGaA%7EDsAxDcBjDuB%7ECcCjCiYhXgMlNeFvGmChDmCnFuBpG%7DAtHkA%60K%5B%60HEdDFjFNrDf%40nFt%40dF%7EAhH%7EF%7CUv%40%7EE%5C%7EDb%40zWLvJRvNj%40bOhA%7CNpAxLfBpOlDr%5BzEfc%40lQn_BtFlg%40%60BrMb%40xBr%40dCfArCjGxJxEvHjG%60L%60NzWlZzk%40lEhJj%40zAnB%7EFbBbHxChO%7EKtj%40fAdGfApKb%40vIHlHIbGoJlnB%7BPtiDyCrj%40a%40jFcAdIgArHy%40vFSbCB%7CEPvBf%40hC%7C%40hCrCfFfBbDfClFfB%7EEdEnMzOzg%40lIfUjIbTfHfRnEjM%40%5C%3FXCTM%5EgAp%40aC%7CAwFhDeHhEgUdN_DlBeCpBgD%7CD%7BBjDyEpI%7BDdFiArAaL%7CLmFjGoKfNwMbRiCrCyCjCcGvD%7DHfEqWrNyXtPgJvFqB%7E%40%7BBb%40yBBmAMmEaAkA%3FmAPs%40RuBnAoC%60BgDxAeB%5EoBJa%40%40iEm%40cGwAoGcAuBOuBBsBZuAd%40yA%60AuAzAy%40jAIf%40_AdCiB%60FmE%7ELq%40%60DY%60DAbAHfERtHEbBk%40nDuAjDwBjCuBxByAzBq%40bAsAbEqAbFmBfJo%40bCuAzCmA%60BgB%7EA%7DDtBgLrFoDfBoBnAoC%7EByDpF%7DDlGwGjKeJbOoHrNyC%7CDkGnG%7DAjCw%40fBwBnGqAbCq%40x%40wAhAsFzDwBxB%7BA%60CcGhKs%40%7EAgAnDuAjGcAlCaAbBsCfD%7DN%7EPwH%60JaExFiEbGyAzAwCtBkAj%40qDpAmLbEwBdAeHdEcIbFcJ%7CFeCdBkAlAgFfJq%40nAwBpC%7DBfBoQjKaMxHmBlBqAvBk%40%7CAaAtEyBjLiG%7E%60%40kA%7CGcAjEaBbGiWh_AgJx%5Cs%40lCeAjFo%40tE%5DhDOfCUd%40c%40L&key=AIzaSyBUjR5xuzBIA_BGGkxnUeHFvLRslstJOU0
That goes in an img tag like so:
<img src="$url_route_img">
Included in an img tag, I see this:
My key is only valid for our server's IP, which is entered in the API key config screen under Restrictions. I've also specifically allowed the Directions and Static Maps APIs on the same key config (the directions part works fine).
What am I missing to get a static image of a route to appear?
Static Maps API requires HTTP based restriction, while Directions was looking for IP based restriction.
I created a second API key specifically for Static Maps and configured using HTTP restriction.
Image now loads perfectly.

Storing a (possibly large) file between requests in Spring

I have this controller methods that depending on the parameters introduced by the user downloads a certain PDF file and shows a view with its different pages converted to PNG.
So the way I approached it works like this:
First I map a method to receive the post data sent by the user, then generate the URL of the actual PDF converter and pass it to the model:
#RequestMapping(method = RequestMethod.POST)
public String formPost(Model model, HttpServletRequest request) {
//Gather parameters and generate PDF url
Long idPdf = Long.parseLong(request.getParam("idPdf"));
//feed the jsp the url of the to-be-generated image
model.addAttribute("image", "getImage?idPdf=" + idPdf);
}
Then in getImageMethod I download the PDF and then generate a PNG out of it:
#RequestMapping("/getImage")
public HttpEntity<byte[]> getPdfToImage(#RequestParam Long idPdf) {
String url = "myPDFrepository?idPDF=" + idPdf;
URL urlUrl = new URL(url);
URLConnection urlConnection;
urlConnection = urlUrl.openConnection();
InputStream is = urlConnection.getInputStream();
return PDFtoPNGConverter.convert(is);
}
My JSP just has an img tag that refers to this url:
<img src="${image}" />
So far this work perfectly. But now I need to allow the possibility of viewing multi page PDFs, converted as PNGS, each of them in a different page. So I would add a page parameter, then feed my model with the image url including that page parameter, and in my getImage method I would convert only that page.
But the way it is implemented, I would be downloading the PDF again for each page, plus an additional time for the view, so it can find out whether this specific PDF has more pages and then show the "prev" and "next" buttons.
What would be a good way to preserve the same file during these requests, so I download it just once? I thought about using temp files but then managing its deletion might be a problem. So maybe storing the PDF in the session would be a good solution? I don't even know if this is good practice or not.
I am using Spring MVC by the way.
I think the simplest way would be using spring cache abstraction. Look at tutorial and will need to change your code a little: move logic that load pdf to separate class.
it will looks like:
interface PDFRepository {
byte[] getImage(long id);
}
#Repository
public class PDFRepositoryImpl implements PDFRepository {
#Cacheable
public byte[] getImage(long id) {
String url = "myPDFrepository?idPDF=" + idPdf;
URL urlUrl = new URL(url);
URLConnection urlConnection;
urlConnection = urlUrl.openConnection();
InputStream is = urlConnection.getInputStream();
return PDFtoPNGConverter.convert(is);
}
}
You will get pluggable cache implementation support and good cache expiration management.

nsIProtocolHandler and nsIURI: Relative URLs in self-created protocol

I have a simple implementation of custom protocol. It's said that newURI method takes 3 arguments (spec, charset & baseURI) and "if the protocol has no concept of relative URIs, third parameter is ignored".
So i open a page like this tada://domain/samplepage which has XML starting with this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Product SYSTEM "product.dtd">
But i don't see any request regarding product.dtd to my protocol (newURI is not even called). Do i miss smth in my implementation?
BTW: the page itself opens correctly, but there's no request to the DTD-file.
const
Cc = Components.classes,
Ci = Components.interfaces,
Cr = Components.results,
Cu = Components.utils,
nsIProtocolHandler = Ci.nsIProtocolHandler;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function TadaProtocol() {
}
TadaProtocol.prototype = {
scheme: "tada",
protocolFlags: nsIProtocolHandler.URI_DANGEROUS_TO_LOAD,
newURI: function(aSpec, aOriginCharset, aBaseURI) {
let uri = Cc["#mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
uri.spec = (aBaseURI === null)
? aSpec
: aBaseURI.resolve(aSpec);
return uri;
},
newChannel: function(aURI) {
let
ioService = Cc["#mozilla.org/network/io-service;1"].getService(Ci.nsIIOService),
uri = ioService.newURI("chrome://my-extension/content/about/product.xml", null, null);
return ioService.newChannelFromURI(uri);
},
classDescription: "Sample Protocol Handler",
contractID: "#mozilla.org/network/protocol;1?name=tada",
classID: Components.ID('{1BC90DA3-5450-4FAF-B6FF-F110BB73A5EB}'),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler])
}
let NSGetFactory = XPCOMUtils.generateNSGetFactory([TadaProtocol]);
The channel you return from newChannel has the chrome:// URI you passed to newChannelFromURI as its URI. So that's the URI the page has as its URI, and as its base URI. So the DTD load happens from "chrome://my-extension/content/about/product.dtd" directly.
What you probably want to do is to set aURI as the originalURI on the channel you return from newChannel.
As Boris mentioned in his answer, your protocol implementation doesn't set nsIChannel.originalURI property so that URLs will be resolved relative to the chrome: URL and not relative to your tada: URL. There is a second issue with your code however: in Firefox loading external DTDs only works with chrome: URLs, this check is hardcoded. There is a limited number of supported DTDs that are mapped to local files (various HTML doctypes) but that's it - Gecko doesn't support random URLs in <!DOCTYPE>. You can see the current logic in the source code. The relevant bug is bug 22942 which isn't going to be fixed.
Boris and Wladimir, thank you!
After some time i have a solution. The problem was that the DTD-file could not be loaded from my custom-created protocol. The idea was to use Proxy API to override schemeIs() method, which was called in newURI method of nsIProtocolHandler.
So now i have this snippet of code in newURI method:
let standardUrl = Cc["#mozilla.org/network/standard-url;1"].createInstance(Ci.nsIStandardURL);
standardUrl.init(standardUrl.URLTYPE_STANDARD, -1, spec, charset, baseURI);
standardUrl.QueryInterface(Ci.nsIURL);
return Proxy.create(proxyHandlerMaker(standardUrl));
proxyHandlerMaker just implements Proxy API and overrides the needed schemeIs() method. This solved the problem and now all the requests come to newChannel where we can handle them.
Important notes:
Request to DTD comes to newURI() method and does not come to newChannel(). This is the default behavior. This happens because schemeIs("chrome") method is called on the object which was returned by newURI() method. This method should return "true" for DTD-requests if you want the request to reach the newChannel() method.
newChannel() method is invoked with the {nsIURI} object which is not the same as the object which was returned by the newURI method.
If you want to handle both protocol:page & protocol://domain/page URLs by your protocol, you should use both {nsIURI} and {nsIStandardURL} objects
You can pass the created {nsIStandardUrl}-object (standardUrl in the snippet above) as a 2nd argument to the Proxy.create() function. This will make your baseURI (3rd arguments in newURI) pass "baseURI instanceof nsIStandardUrl" check. SchemeIs() method of this proxied object will also return true for the DTD-files requests. But unfortunately the requests won't reach newChannel() method. This could be a nice DTD-problem solution but I can't solve this problem.

JAX-RS : When we send back an image, in which format is it received by the client?

I have the following code to send images to the client :
#GET
#Path("/images/{image}") #Produces("image/*")
public Response getImage(#PathParam("image") String image) {
File f = new File(image);
if (!f.exists()) {
throw new WebApplicationException(404);
}
String mt = new MimetypesFileTypeMap().getContentType(f);
return Response.ok(f, mt).build();
}
Now, the client will receive the image in which format ? Will it be wrapped in XML, or as raw binary ? If I simply put the response in the src of an image tag, will the image be rendered ?
If not, how can I make the raw binary stream that is returned, into an image that can be placed in an img tag
ad 1) File will be serialized as raw binary (opened stream will be directly returned)
ad 2) you mean location of the resource which is returning image as a file, right? if so, then the answer is yes (you can't just put raw binary data into html page like "<img src="<binary_data>" />)
You can also add content type to your response header e.g. image/jpeg , image/png or image/gif so that the client can decide for himself as to what is the type of image by reading the response header.
One more thing if the url you are posting to is returning image stream there is no need for an ajax request. If its a servlet you can jsut add the servlet url to image src, and it'll work.

Resources