AnsweredAssumed Answered

request a png image using NodeJS and dojo/request from an ArcGIS Server REST feed, and return the image to the client

Question asked by thomas.giles@ec.gc.ca on Dec 17, 2015
Latest reply on Mar 29, 2016 by thomas.giles@ec.gc.ca

I am attempting to request a png image using NodeJS and dojo/request from an ArcGIS Server REST feed, and return the image to the client.

I need nodeJS to add a token to the request as a query parameter as my services are secured and I want to control their security through node and not on the resource server (ArcGIS Server 10.3). Without nodeJS in the picture, the png loads in the browser. This is an (open) example of a call returning a png image, using their standard REST feed:

https://sampleserver6.arcgisonline.com/arcgis/rest/services/911CallsHotspot/MapServer/1/images/257104fa1b21d7b483c160ee8f3943bb

I am using dojo/request to access this resource. It seems the png image is coming back to node fine, however when I res.send() back to the client, I get a 'not an image' in Fiddler. I can see the PNG header, and the IHDR and IEND in the hexview, however it is apparent that the encoding (? or other) is not the same as when the resource is returned directly from the ArcServer. When the png is received on the client returned from node, the content-length is a little less than when the same png comes directly from the ArcServer. (Node is attempting, by its default, to use Transfer-Encoding: Chunked. I set content-length to the length of the response, so it sends at one time, which I believe is the behaviour the client is expecting.)

ESRI (ArcGIS Server) have a new sample stub out which does exactly what I want to do, however they are using esri/request (built on dojo/request) client side, and leverage Blob library to create the correct response for the client.

https://developers.arcgis.com/javascript/jssamples/data_requestArrayBuffer.html

We can see they use handleAs: "arrayBuffer", which I have tried on dojo/request and it seems to make no difference to the content of the returned png. When they receive the response, they make a new Blob and then read it as data URL with FileReader (which I have a node side implementation of) and directly use that result as the png.

I have tried ad-nausuem to replicate this, but it seems that node does not have a reliable Blob library (I have tried "Blob" with no luck) and I read that in node you are supposed to use Buffers instead. No matter what I pass to fileReader, I get the error "Cannot read as File" (I have tried all fileReader methods). The fileReader library: https://www.npmjs.com/package/filereader

ESRI code:

esriRequest(url, {handleAs: "arrayBuffer"}).then(function(response) { reader.readAsDataURL(new Blob([response], { type: "image/png" })); //reader.result is png ready to use client side });

My attempts:

//tried handleAs: "arrayBuffer"

//tried npm Blob library

request(url, {handleAs: "arrayBuffer"}).then(function(response) { var reader = new FileReader(); reader.addEventListener("loadend", function() { res.setHeader('Content-Type', 'image/png'); res.setHeader('Content-Length', reader.result.length); res.send(reader.result); }); reader.readAsDataURL(new Blob([response], { type: "image/png" })); });

I am using node package filereader and Blob, with no luck creating a blob to pass to fileReader. If nodeJS uses Buffers instead of Blob, given that the content returned by the service appears to be an ArrayBuffer png, how do I pass that back to the client, through node?

I have also attempted to use ArrayBuffer to Buffer methods (through Uint8Array) however once I have the png in buffer form I can never read it.

In short, I just want to proxy the png from its source to the client, adding a token query parameter.

Comments welcome to improve the question.

 

originally posted here:

http://stackoverflow.com/questions/34341327/dojo-request-a-png-image-array-buffer-using-nodejs-and-return-the-image-to-t…

Outcomes