Sunday, April 18, 2021

show an image from binary data using php

This SO link gives two techniques - using data URIs and using a helper function to fetch the image from some storage location. 

Edit: My initial implementation was using the simpler data URI method. Later, also implemented using the other method. 

Intially,

    // to prevent images from being dropped due to timeouts, we'll encode them inline
    // https://ads-developers.googleblog.com/2013/11/how-to-send-pdf-reports-with-adwords.html

    // to parse the img src, we'll use regex, since the html is of limited scope
    // https://stackoverflow.com/questions/14939296/extract-image-src-from-a-string/15013465
    // https://support.google.com/a/answer/1346938

    var m;
    imageurls = [];
    regexstring = '(http\\S*' + currentTicket +')'; // the \ is escaped, so it becomes doubled.
    //Logger.log(regexstring);
    //myregex = new RegExp(/(http\S*0d0a226a47229313863)/,"gi");    // the ticket is the string after S*
    myregex = new RegExp(regexstring, "gi");
    
    var imageindex=1;

    while ( m = myregex.exec( contentdata ) ) {
      imageurls.push( m[1] );
      //Logger.log(m[1])
      var imagemimetypeandenc = 'data:image/png;base64,'; // default
      if ( m[1].includes('.jpg?ticket') || m[1].includes('.jpeg?ticket') ) {
        imagemimetypeandenc = 'data:image/jpeg;base64,';
      }
      else if ( m[1].includes('.gif?ticket') || m[1].includes('.GIF?ticket') ) {
        imagemimetypeandenc = 'data:image/gif;base64,';
      }
      else if ( m[1].includes('.tif?ticket') || m[1].includes('.tiff?ticket') ) {
        imagemimetypeandenc = 'data:image/tiff;base64,';
      }

      Logger.log('%s of assetid %s',imageindex.toString(),data_array[i][0].toString());
      imageindex = imageindex + 1;
      var imageBlob = UrlFetchApp.fetch(m[1]).getBlob();
      var base64EncodedBytes = Utilities.base64Encode(imageBlob.getBytes());
      var imageencoded = imagemimetypeandenc + base64EncodedBytes;
      contentdata = contentdata.replace(m[1], imageencoded);

    }

and later, when images were available on Google Drive,

  var placeholder = 'data:image/png;base64,iVBORs_a_few_kb_of_chars_QAAAABJRU5ErkJggg==';
  // made with https://www.w3docs.com/tools/image-base64

.....
var m;
    imageurls = [];
    regexstring = 'img\\s*src\\s*=\\s*"(http\\S*)"'; // the \ is escaped, so it becomes doubled.
    // Only the http part is captured, within parenthesis
    // currently it matches only if the img src is within double quotes. "https://whatever"
    //Logger.log(regexstring);
    
    myregex = new RegExp(regexstring, "gi");
    var imageindex=1;

    while ( m = myregex.exec( contentdata ) ) {
      imageurls.push( m[1] );
      
      Logger.log('%s of assetid %s',imageindex.toString(),data_array[i][0].toString());
      imageindex = imageindex + 1;
      
      // here we use a helper if the url contains the alfresco url
      var response;
      if (m[1].includes('ticket=') ) {
        //use the helper function after extracting the filename
        Logger.log('Downloading %s using Alfresco helper', m[1])
        var fname = m[1].split('/')[9]; // from the url similar to 
        // https://www.ourdomain.tld/alfresco/d/direct/workspace/NameOfStore/f8b56b7c-long-id-a35c30be756a/filename-15092020100930PM?ticket=
        fname = fname.split('?')[0];
        // handle cases where fname does not have extension
        var urlFromHelper = UrlFetchApp.fetch(returnUrl+encodeURIComponent(fname));
        response = UrlFetchApp.fetch(urlFromHelper, { muteHttpExceptions: true });
      } 
      
      
      if (response.getResponseCode()==200) {
        var imageBlob = response.getBlob();
        var base64EncodedBytes = Utilities.base64Encode(imageBlob.getBytes());
        //var ctype = response.getHeaders().Content-Type
        var headermap = new Map(Object.entries(response.getHeaders()));
        var mimetypeofim = headermap.get('Content-Type');
        var imagemimetypeandenc = 'data:'+mimetypeofim+';base64,';

        var imageencoded = imagemimetypeandenc + base64EncodedBytes;
        contentdata = contentdata.replace(m[1], placeholder);
      }
      

And in cases where we did not want the images to be base64 encoded - for example in the case of large images, which would cause the function to run out of memory - the whole code-block above would be not needed, since the img src link in the original html would work OK.

No comments:

Post a Comment