Search code examples
node.jsfilegetloopbackjs

How to read an image and text at the same time in Loopback/NodeJs


I am doing a remote method with Loopback to show some text and display an image. I am getting the path of the image and the fields by an sql query and data is showed correctly. What I want to do is to transform the path showed in the result to display the image itself.

This is my remote method so far :

  cm_comediens.getprofile1 = function (options, cb) {
    const token = options && options.accessToken;
    const userId = token && token.userId;

    var ds = app.datasources.mydb;
    var sql = "SELECT comedien_perso_nom,comedien_perso_prenom,nationalite,photoscomedien.path FROM cm_comediens INNER JOIN photoscomedien ON cm_comediens.id_comedien=photoscomedien.id_comedien WHERE cm_comediens.id_comedien IN ( SELECT id_comedien FROM (SELECT id_comedien FROM cm_comediens WHERE id_utilisateur= '" + userId + "') as MakeitWork) AND photoscomedien.photo_profile=1  ";
    ds.connector.execute(sql, [], function (err, cm_comedienss) {
    if(err) {console.error(err);}
    cb(err, cm_comedienss);    
    }); 
    }

  cm_comediens.remoteMethod(
    'getprofile1', {
      http: {verb: 'GET'},
      description: 'Get Comediens infos',
      accepts: [{arg: "options","type": "object","http": "optionsFromRequest"},],
      returns: {arg: 'data',type: ['cm_comediens'],root: true,}
    }
  );

This is what I am getting so far and what I want to do exactly is to change the path to an image

Result

I tried to add the fs.readfile but weird result showed up. I changed the remote method as follows :

ds.connector.execute(sql, [], function (err, cm_comedienss) {
fs.readFile(cm_comedienss[0].path, function(err, cm_comedienss) {
if(err) {console.error(err);}
cb(err, cm_comedienss);    
}); 
});
}

This is the result I got after adding the readfile :

after adding fs.readfile


Solution

  • The remoting metadata for your new method are describing the return value as a JSON data. The actual value is Buffer, which is converted by LoopBack to the value you shown on your screenshot.

    {
      "$type": "base64"
      "$data": "(base64-encoded data of your image)" 
    }
    

    If you want your API to return image, you need to make two changes:

    • tell LoopBack to set a different Content-Type header, e.g. image/png
    • tell LoopBack to treat the Buffer value as the raw response body
    cm_comediens.getprofile1 = function (options, cb) {
      ds.connector.execute(sql, [], function (err, found) {
        if (err) return cb(err);
    
        fs.readFile(found[0].path, function(err, image) {
          if(err) return cb(err);
    
          cb(null, image, 'image/png');
        });
      });
    };
    
    
    cm_comediens('getprofile1', {
      http: {verb: 'GET'},
      description: 'Get Comediens infos',
      accepts: [
        {arg: "options","type": "object","http": "optionsFromRequest"},
      ],
      returns: [
        { arg: 'body', type: 'file', root: true },
        { arg: 'Content-Type', type: 'string', http: { target: 'header' } },
      ],
    });