How to use XMLHttpRequest with Open Layers - javascript

I need to get images from multiple WebMapServers (of my company) with Open Layers (and pure Javascript).
Basically it works. Problem is that some servers require HTTP Basic Auth. The OL documentation and a related SO question say that this should be done with a XMLHttpRequest inside an imageLoadFunction:
https://openlayers.org/en/latest/apidoc/module-ol_Image.html
How to assign basic authentication header to XMLHTTPREQUEST?
At first I want to get images with XMLHttpRequest and without Basic Auth:
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Image({
source: new ol.source.ImageWMS({
ratio: 1,
params: { LAYERS: 'ENC', CSBOOL: '2083', CSVALUE: ',,,,,3'},
url: 'https://wms-without-basic-auth.com/?',
imageLoadFunction: function(image, src) {
image.getImage().src = src;
/*
var client = new XMLHttpRequest();
client.open('GET', src, true);
client.setRequestHeader( 'Content-Type', 'image/png' );
client.setRequestHeader( 'Accept', 'image/png' );
client.onload(function() {
image.getImage().src = src;
});
client.send();
*/
},
})
})
],
view: new ol.View({
center: ol.proj.fromLonLat([6,54]),
zoom: 6
})
});
The imageLoadFunction only works with the line
image.getImage().src = src;
but not with the commented XMLHttpRequest.
I think the loaded image must be assigned in the client.onload function, but I'm not sure how to do this.
So how should I use the XMLHttpRequest inside the imageLoadFunction?

From the docs:
Providing a custom imageLoadFunction can be useful to load images with post requests or - in general - through XHR requests, where the src of the image element would be set to a data URI when the content is loaded.
Maybe try something like this:
imageLoadFunction: function(image, src) {
var client = new XMLHttpRequest();
client.open('GET', src, true);
client.setRequestHeader( 'Content-Type', 'image/png' );
client.setRequestHeader( 'Accept', 'image/png' );
client.responseType = 'blob';
client.onload(function() {
const blob = new Blob(client.response);
const urlData = URL.createObjectURL(blob);
image.getImage().src = urlData;
});
client.send();
},
What it does:
gets your image from your server
Create a blob
Converts the blob to urlData
Finally uses the urlData as source for your image

Related

ArrayBuffer to jpeg

I am streaming ArrayBuffers from a python server and am trying to interpret each one as an image on the client side with javascript. They are being received as arraybuffers in javascript. However I cant get them to be readable by the image tags src attribute. I have tried generating them into Blob objects then using window.URL.createObjectURL(blob). That hasnt work either.
The blob url looks like this blob:null/e2836074-64b5-4959-8211-da2fc24c35a6 is that wrong?
Does any have any suggestions/know a solution.
Thanks a lot.
var arrayBuffer = new Uint8Array(stream.data);
var blob = new Blob([arrayBuffer], {type: "image/jpeg"});
var urlCreator = window.URL || window.webkitURL;
var imageUrl = urlCreator.createObjectURL( blob );
console.log(imageUrl);
img.src = imageUrl;
array buffer image
If you have any control over things, you should use the responseType of blob on your Javascript call. This will let you use the data you are getting from your server directly instead of attempting to access it via an ArrayBuffer
See the following fiddle for an example: https://jsfiddle.net/ort74gmp/
// Simulate a call to Dropbox or other service that can
// return an image as a blob
var xhr = new XMLHttpRequest();
// Use JSFiddle logo as a sample image to avoid complicating
// this example with cross-domain issues.
xhr.open( "GET", "https://fiddle.jshell.net/img/logo.png", true );
// Ask for the result as an ArrayBuffer.
xhr.responseType = "blob";
xhr.onload = function( e ) {
var blob = this.response;
var reader = new FileReader();
reader.onload = function() {
var dataURL = reader.result;
document.querySelector('#photo').src = dataURL;
}
reader.readAsDataURL(blob);
};
xhr.send();

Openlayers authorization authentication [duplicate]

some wms or wfs sources require user and password authentication.
for example https://apps.sogelink.fr/maplink/public/wfs?request=GetCapabilities
need Basic authentication.
How can I inject this authentication?
You can provide your own imageLoadFunction to an ImageWMS source.
The default one just takes the URL and inserts it as the src of the img tag:
ol.source.Image.defaultImageLoadFunction = function(image, src) {
image.getImage().src = src;
};
That question was already asked on the OpenLayers GitHub, here is an example from there:
function customLoader(tile, src) {
var client = new XMLHttpRequest();
client.open('GET', src);
client.setRequestHeader('foo', 'bar');
client.onload = function() {
var data = 'data:image/png;base64,' + btoa(unescape(encodeURIComponent(this.responseText));
tile.getImage().src = data;
};
client.send();
}
The documentation of OpenLayers is really good. Just find an example that uses features you want and then follow the links to the API docs.The ol.source.Vector doc even includes an example of a loading function for WFS, where you could manipulate the request:
new ol.source.Vector({
format: new ol.format.GeoJSON(),
loader: function(extent, resolution, projection) {
var wfsUrl = 'TODO';
var xhr = new XMLHttpRequest();
// see above example....
}
});

xhr.onload too slow in android

I need to display image/jpeg in my web application as well as android app with same code and used the below working javascript code for the same:
var xhr = new XMLHttpRequest();
xhr.open('GET', value, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function (e) {
var arrayBufferView = new Uint8Array( this.response );
var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } );
var urlCreator = window.URL || window.webkitURL;
localSrc = urlCreator.createObjectURL( blob );
var img = new Image();
img.src=localSrc;
$('#jpg'+i).append(img);
};
xhr.send();
The performance is too slow when tested in android 4.4.2, like its waiting to send the xhr request after collecting all the image url's. Delay is more in android compared to web application .
How can I improve the performance ? Is there any other method to do the same with better performance?

Angular JS with PDFTron

I am trying to get a blob as a URL but i get an error on this line :
xhr.send()
The error message is angular.js:13920 Error: Failed to execute 'send' on 'XMLHttpRequest': The object's state must be OPENED.
But in the code I am using xhr.open('GET', blobValue) as shown in my code here
if(someBlobValue){
var viewerElement = $document[0].getElementById('viewer');
var myWebViewer = new PDFTron.WebViewer({
path: 'lib',
pdftronServer: 'https://demo.pdftron.com' // remove
}, viewerElement);
var xhr = new XMLHttpRequest;
xhr.responseType = 'blob';
xhr.onload = function() {
var recoveredBlob = xhr.response;
var reader = new FileReader;
reader.readAsDataURL(recoveredBlob);
};
xhr.open('GET', someBlobValue);
xhr.setRequestHeader('Content-type', 'application/pdf');
xhr.send(); //error here although its open?
//var file = new File([newValue], 'somefile.pdf');
myWebViewer.loadDocument(xhr.response, { filename: 'somefile.pdf'});
Currently i have the document as a blob but i am trying to load it to pdftron library and unfortunately i dont seem to find the myWebViewer.getInstance().loadLocalFile method in the DOM (its undefined).
Would appreciate any pointers as its the first time trying to use pdftron in the angularjs app.
NOTE : This is inside a directive.
You need to wait for the DOM element containing WebViewer to trigger the ready event, for the ReaderControl instance, returned from getInstance(), to be defined.
For example:
$(viewerElement).on('ready', function() {
myWebViewer.getInstance().loadLocalFile(someBlobValue);
});
There is nothing wrong in your code logically,
You just forgot to instantiate the XHR object over here var xhr = new XMLHttpRequest;.
You can correct it by doing this var xhr = new XMLHttpRequest();

Load image into FileReader

I want to load an image from an url into filereader in order to obtain a data url of that image. I tried to search for the solution on google but i can only find solutions to read them from the file input on a local computer.
If you want a usable data-URI representation of the image, then I suggest to load the image in a <img> tag, paint it on a <canvas> then use the .toDataURL() method of the canvas.
Otherwise, you need to use XMLHttpRequest to get the image blob (set the responseType property on the XMLHttpRequest instance and get the blob from the .response property). Then, you can use the FileReader API as usual.
In both cases, the images have to be hosted on the same origin, or CORS must be enabled.
If your server does not support CORS, you can use a proxy that adds CORS headers. In the following example (using the second method), I'm using CORS Anywhere to get CORS headers on any image I want.
var x = new XMLHttpRequest();
x.open('GET', '//cors-anywhere.herokuapp.com/http://www.youtube.com/favicon.ico');
x.responseType = 'blob';
x.onload = function() {
var blob = x.response;
var fr = new FileReader();
fr.onloadend = function() {
var dataUrl = fr.result;
// Paint image, as a proof of concept
var img = document.createElement('img');
img.src = dataUrl;
document.body.appendChild(img);
};
fr.readAsDataURL(blob);
};
x.send();
The previous code can be copy-pasted to the console, and you will see a small image with YouTube's favicon at the bottom of the page. Link to demo: http://jsfiddle.net/4Y7VP/
Alternative download with fetch:
fetch('http://cors-anywhere.herokuapp.com/https://lorempixel.com/640/480/?
60789', {
headers: {},
}).then((response) => {
return response.blob();
}).then((blob) => {
console.log(blob);
var fr = new FileReader();
fr.onloadend = function() {
var dataUrl = fr.result;
// Paint image, as a proof of concept
var img = document.createElement('img');
img.src = dataUrl;
document.body.appendChild(img);
};
fr.readAsDataURL(blob);
}).catch((e) => console.log(e));

Categories

Resources