Loading image source bytes

Hey everyone,

I’ve been trying to get this to work for a while to no avail.

So I created a node test server that serves up images.

app.get('/picture', function(req, res) {
    res.type('jpg');
    res.sendFile(__dirname + '/picture/image.jpg');
});

I have tested this and if I just navigate to the route “http://localhost:8080/picture” it will serve the picture in the browser no problem.

So in my ionic test app I have an image tag defined in the html like this:

<div class="list card">
    <div class="item item-divider">
        <button class="button" ng-click="imageButtonOnClick()">Get Image</button>
    </div>
    <div class="item item-body">
        <img ng-src="{{image.uri}}" />
    </div>
</div>

And in the controllers.js file I have the following:

$scope.image = {
    uri: ''
};

$scope.imageButtonOnClick = function() {	
    $.ajax({
        type: "GET",
        url: "http://localhost:8080/picture/",
        data: {
            email: 'test@test.com,' // Want to deny serving image on invalid credentials
            sessionId: '1234',
            miscData: 'blah'
        },
        dataType: "text",
        success: function(res) {
            $scope.image.uri = 'data:image/jpg;base64,' + res;
            $scope.$apply();
        },
        error: function(err) {
            console.log('Error: ' + JSON.stringify(err));
        }
    });
};

I have the following as my whitelisting:

.config(function($compileProvider){
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel|blob):|data:image\//);
})

When I click the button it just shows a blank outline like it tried to display the picture. The console has no errors. I can throw a console.log(res) in the success callback and it shows a series of bytes like this: ‘\u0012’. Some show as question marks since they are probably extended ascii characters.

When I try to send back a ‘png’ instead of a ‘jpg’ it shows an icon of a broken image and in the console it says: “Failed to load resource: net::ERR_INVALID_URL”

Anybody have an idea of where I am going wrong with this?

I found this post where he is trying to load the image in a canvas. If possible I don’t want to use a canvas.

Let me know if you need more information. I will provide what I can.

Thanks!

you have a express app?

Then you have to start a static file server, to be able to serve files from your server to the client.
What you are doing is -> sending a string (in this case a file path) to the frontend, but there is no file-server where the frontend can get the content.

Like in most apis, you have a folder where static / public files were stored (like uploads and so on).
In your nodejs-app add

app.use(express.static('PATH TO YOUR STATIC FILES')); // static file server

before you define your routes.

1 Like

Thanks for the response. I did forget to mention that I do have that set up in my example as well.

app.use(express.static(__dirname + ‘/picture/’));

But I believe this is only if I want to access the static files directly?
Say I have image in path “picture/image.jpg”, if I used that use statement I should be able to access directly using uri “http://localhost:8080/image.jpg” instead of “http://localhost:8080/picture/image.jpg” or whatever.

In my server I am explicitly grabbing a file and sending it via sendFile().

The goal I am trying to achieve is to create a way to give and deny access to images based on user credentials.

Are you trying to show a bytestream directly in the template?

ng-src can only show the image directly via path or base64.

I think your result of sendFile is a bytestream, so you have to encode it first to base64

1 Like

I tried the following:

Also just tried plain atob, btoa, encodeURI / encodeURIComponent, and decodeURI / decodeURIComponent.

I’ve tried:

document.write('<img src="data:image/jpg;base64,' + res + '"/>');

to see if it had something to do with the binding (which I doubted it would since it showed what I expected when inspecting the element), and it didn’t.

I inspected the element and the console log to see what is being injected into the HTML and the base64 string ‘looks’ like how the other examples online are once encoded. I opened up the image via vim and saw that it looks exactly like what is returned from express.

When simply navigating to ‘localhost:8080/picture/’, the image shows. I inspected the image and it’s just placing the url in the src:

<img src='http://localhost:8080/picture' />

Which would work great except I will need to be able to pass body data that I don’t want to expose in the query uri. Such as:

<img src='http://localhost:8080/picture?cred=exposed;sessionId=exposed;pictureId=exposed;etc...'>

Here is what I have now.

$scope.utf8_to_b64 = function(str) {
    return window.btoa(unescape(encodeURIComponent(str)));
};
$scope.b64_to_utf8 = function(str) {
    return decodeURIComponent(escape(window.atob(str)));
};
$scope.imageButtonOnClick = function() {	
    $.ajax({
        type: "GET",
        url: "http://localhost:8080/picture/",
        data: {
            test: '1'
        },
        dataType: "text",
        success: function(res) {
            //console.log('Decode: ' + decodeURI(res));
            $scope.image.uri = 'data:image/png;base64,' + $scope.utf8_to_b64(res);
            //console.log($scope.utf8_to_b64(res));
            //document.write('<img src="data:image/png;base64,' + $scope.utf8_to_b64(res) + '" />');
            $scope.$apply();
        },
        error: function(err) {
            console.log('Error: ' + JSON.stringify(err));
        }
    });
};

Any tips?