0

I have an app that is written and working in Google Apps script. It grabs an image from Google Drive, converts it to a blob, and sends it to an external API via the request body.

I am converting this app to nodejs and using an Azure Storage Account to store the images now, but still calling the same external API.

In Google Apps script, to get the Google Drive image blob to send to the external API, I use DriveApp.getFileById().getBlob(). This is not a string, but a blob itself.

What do I use in node.js for Azure blob storage?

I have tried to use getBlobToText, before understanding that's not what the API wants. It doesn't want a string, but the blob itself. I have looked at getBlobToStream and others as well, but none of them seem to actually get the blob itself.

I have read many, many stackoverflow Q&As, along with many other articles and sites, but to can't find any talking about using a downloaded Azure blob to send to an external API.

Chris
  • 473
  • 5
  • 18

1 Answers1

0

In Azure SDK, you can download the blob as Stream/string. And, that is how it works in enterprise applications as well. You can download blob like below:

// Get blob content from position 0 to the end
// In Node.js, get downloaded data by accessing downloadBlockBlobResponse.readableStreamBody
// In browsers, get downloaded data by accessing downloadBlockBlobResponse.blobBody
const downloadBlockBlobResponse = await blockBlobClient.download(0);
console.log('\nDownloaded blob content...');
console.log('\t', await streamToString(downloadBlockBlobResponse.readableStreamBody));

Helper function to convert to string:

// A helper function used to read a Node.js readable stream into a string
async function streamToString(readableStream) {
  return new Promise((resolve, reject) => {
    const chunks = [];
    readableStream.on("data", (data) => {
      chunks.push(data.toString());
    });
    readableStream.on("end", () => {
      resolve(chunks.join(""));
    });
    readableStream.on("error", reject);
  });
}

You can then send this response to your external API.

I am not sure about your requirements but this is not the right approach as it will have security concerns. You can give external API a reader role using RBAC to your Azure Blob storage and let external API read blob directly from the storage.

Harshita Singh
  • 4,590
  • 1
  • 10
  • 13
  • Thank you, @singhh-msft ! I got the code to work as you described above. It does do what the code should do, according to what I see. However, the API I am calling, does not seem to think it is in the correct format it is looking for. When I do a console.log in Google Apps Script after using DriveApp.getFileById().getBlob(), as I described above, it just says "blob". However, when I do a console.log of the result of the streamToString above, it gives me pages and pages of characters. So, there seems to be a diff between the two that causes the API to not attach the picture. Thoughts? – Chris Feb 28 '21 at 23:45
  • If you look at the Google Apps Script getBlob() description (https://developers.google.com/apps-script/reference/drive/file#getblob), it says it returns "Blob - The data as a blob". Then according to the link you posted above (https://docs.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-nodejs#download-blobs), it says that it "used to read a Node.js readable stream into a string". I'm not experienced enough with blobs to know if those are diff for sure, but they seem to be according to console.log & the API seemingly disregarding what I send it from Azure using above code. – Chris Feb 28 '21 at 23:53
  • Here is the URL of the very similar question on stackoverflow I had a year ago when I was writing this in Google Apps Script and trying to figure out how to get the image to send to the API: https://stackoverflow.com/q/60349383/12942220. Here is the API doc, which shows the "upload" field (image) I am talking about: https://www.projectbroadcast.com/apidoc/?fbclid=IwAR3PcGG6oVHKmXDxWeX98K-vb1HMyJIBnSSbBOlI9vFD3FmK09kZkhrZDDs#api-Contacts-Send_Message – Chris Mar 01 '21 at 00:06
  • Can you change external API's code to process Stream/String of Blobs? – Harshita Singh Mar 01 '21 at 05:33
  • Unfortunately the external API's code is not ours. It is a 3rd party. So, we cannot change it. – Chris Mar 01 '21 at 15:33
  • What I do know is that using Google's DriveApp.getFileById().getBlob() works. developers.google.com/apps-script/reference/drive/file#getblob. But, I can't use that in nodejs, and obviously wouldn't as I want to use Azure Blob Storage. – Chris Mar 01 '21 at 15:40
  • This is the only way, your 3rd Party app code has to change, or you will have to save it to both Blob and Google Drive and create another API to read and send it to your 3rd party API – Harshita Singh Mar 01 '21 at 15:48
  • The API (https://www.projectbroadcast.com/apidoc/#api-Contacts-Send_Message) says that "Media must be smaller than 1.5mb". Could it by chance be a problem with the "block size" being 4 MB? When I upload an image to Azure Storage, if I set the Block size to something like 512 KB or 1 MB, would that possibly help? OR uploading to Azure Storage as a different Blob Type, such as "Page Blob" or "Append Blob"? – Chris Mar 01 '21 at 16:24
  • Yes, as written in the API documentation, you have to send blobs smaller than 1.5MB only. Further, block blob should work. Do check out this: https://learn.microsoft.com/en-us/rest/api/storageservices/understanding-block-blobs--append-blobs--and-page-blobs. – Harshita Singh Mar 01 '21 at 16:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/229373/discussion-between-chris-and-singhh-msft). – Chris Mar 02 '21 at 01:00