Fetch image from azure-blob and send it to client without saving locally using node server

2.6k views Asked by At

I want to fetch image from azure blob storage and send it over to client without saving it locally. I am able to get image from blob storage and save it to local file but struggling to send it to client without saving locally. Please find code below

    const containerClient = blobServiceClient.getContainerClient(containerName);
    const blockBlobClient = containerClient.getBlobClient(blobName);

    const downloadBlockBlobResponse = await blockBlobClient.download(0);
    console.log('\nDownloaded blob content...');
    let f = await streamToString(downloadBlockBlobResponse.readableStreamBody)
    
    reply.type('image/jpg').send(f)

streamToString function is as follows

     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);
     });
}

I get blank screen in browser when I run this code

enter image description here

1

There are 1 answers

3
Stanley Gong On BEST ANSWER

If you want to fetch an image from azure blob storage and send it over to the client without saving it locally, the Node server sending a SAS token to the client and the client get this image from Azure storage directly would be a better solution I think. It also eases the pressure of the Node server: generate a SAS token and send it to the client is ok, no need to read data from Storage.

Try the code below to generate a SAS token:

var azure = require('azure-storage');
    var connString = "your storage connection string";
    var container ="your container name";
    var blobName = "your image name"
    var blobService = azure.createBlobService(connString);

    // Create a SAS token that expires in an hour
    // Set start time to five minutes ago to avoid clock skew.
    var startDate = new Date();
    startDate.setMinutes(startDate.getMinutes() - 5);
    var expiryDate = new Date(startDate);
    expiryDate.setMinutes(startDate.getMinutes() + 60);
    


    var sharedAccessPolicy = {
        AccessPolicy: {
            Permissions: [azure.BlobUtilities.SharedAccessPermissions.READ],  //grent read permission only
            Start: startDate,
            Expiry: expiryDate
        }
    };
    
    var sasToken = blobService.generateSharedAccessSignature(container, blobName, sharedAccessPolicy);
    
    var response = {};

    response.image = blobService.getUrl(container,blobName,sasToken);
    
    res.send(response);

Result: enter image description here

Client-side could use this image URL to access this image directly from storage:

enter image description here

Try this to convert imageURL to base64 image content so that you can save/show images directly based on their content:

<html>

<body>
    <img id="displayImg">
</body>


<script>

var nodeResult = {"image":"https://stantest1016.blob.core.windows.net/stantest/test.jpeg?st=2020-10-26T04%3A53%3A51Z&se=2020-10-26T05%3A53%3A51Z&sp=r&sv=2018-03-28&sr=b&sig=ZjY3LYbgvMn%2BSr4dAEUoqidVRT4YyH1FcW1DeKlpjYo%3D"}


function getImageData(nodeResult){


var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        var reader = new FileReader();
        reader.readAsDataURL(this.response);
        reader.onload = function() {
            document.getElementById('displayImg').src = reader.result;
        }
  };
    
   
    
  };
  xhr.open('GET', nodeResult.image);
  xhr.responseType = 'blob';
  xhr.send();

}


getImageData(nodeResult);
</script>

</html>

Result:

enter image description here

Details of tag: enter image description here