2
votes

I want to upload profile picture of a user sent from web app and mobile app via Base64 form.

On the POST request they need to send a JSON on the body that looks something like this.

{
    "name":"profile-pic-123.jpg",
    "file":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxQTEhIUEhIUFBUV…K9rk8hCAEkjFMUYiEAI+nHIpsQh0AkisDYRTOiCAbWVtgCtI6IlkHh7LDTQXLH0EIQBj//2Q==" // the base64 image
}

Now on the server side using Node and Express, I used this npm module called azure-storage which offers a nice way of uploading files to azure blob storage using web service.

But there's something that I cannot understand on this. Here's a part of the code from my controller. I successfully created all neccessary connections and keys and whatnot to create a working blobService :

controllers.upload = function(req, res, next){

    // ...
    // generated some sastoken up here
    // etc.
    // ...

    var uploadOptions = {
        container: 'mycontainer',
        blob: req.body.name, // im not sure about this
        path: req.body.file // im not sure about this either
    }

    sharedBlobService.createBlockBlobFromLocalFile(uploadOptions.container, uploadOptions.blob, uploadOptions.path, function(error, result, response) {
        if (error) {
            res.send(error);
        }
        console.log("result", result);
        console.log("response", response);
    });
}

Im getting this error:

{
    "errno": 34,
    "code": "ENOENT",
    "path": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAAB..."
}
2

2 Answers

3
votes

In this case, you should not use createBlockBlobFromLocalFile. Instead, you should use createBlockBlobFromText, because you are not uploading a local file, but content in the request body.

Here is the code:

var uploadOptions = {
    container: 'mycontainer',
    blob: req.body.name, 
    text: req.body.file 
}

sharedBlobService.createBlockBlobFromText(uploadOptions.container, 
                                           uploadOptions.blob, 
                                           uploadOptions.text, 
                      {
                         contentType: 'image/jpeg',
                         contentEncoding: 'base64'
                      }, 
                      function(error, result, response) {
                           if (error) {
                               res.send(error);
                           }
                           console.log("result", result);
                           console.log("response", response);
                      });

The blob is just the file name, which is "profile-pic-123.jpg" this case, and path is the local path to your file. Since you are not storing the file locally in the server side, path is meaningless in the case.

If you need more information about Storage, see this, and this

2
votes

if you use javascript sdk v12 You can use this sample code. It's just that simple. I have this implemented in a function and it works great when all I need it to trigger an HTTP event.

index.js

 const file = await require('./file')();
    uploadOptions = {
        container: 'mycontainer',
        blob: req.body.name, 
        text: req.body.file 
    }

      const fileUploader = await file(uploadOptions.text, uploadOptions.blob, 

uploadOptions.container);

You can use a separate module for your logic and call this from the index.js above

file.js

    const { BlobServiceClient } = require("@azure/storage-blob");
    const blobServiceClient = BlobServiceClient.fromConnectionString(process.env.AZURE_STORAGE_CONNECTION_STRING);
const Promise = require('bluebird');

    module.exports = Promise.method(async function() {

        return async function (data, fileName, container) {
            const containerClient = await blobServiceClient.getContainerClient(container);
            const blockBlobClient = containerClient.getBlockBlobClient(fileName);
            const matches = data.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);
            const buffer = new Buffer(matches[2], 'base64');

            return await blockBlobClient.upload(buffer, buffer.byteLength );
        };
    });