Upload a Stream to Azure Blob Storage using REST API without Azure SDK Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Upload a Stream to Azure Blob Storage using REST API without Azure SDK without wasting too much if your time.

The question is published on by Tutorial Guruji team.

I wish to upload files in the form of a stream into Azure Storage but I don’t want to use Azure SDK instead I want to do it in a more generic way using REST API and not BlobServiceClient.

Is there a way to do so? The reference links for the same can be found here:

https://docs.microsoft.com/en-us/azure/storage/common/storage-samples-javascript?toc=/azure/storage/blobs/toc.json#blob-samples

https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/storage/storage-blob/samples/javascript/advanced.js#L74

But the links mentioned here propose a solution using Azure SDK. I want to do it without Azure SDK

Here’s the code:

const CryptoJS = require("crypto-js");
const request = require("request");
const fs = require("fs");

const account = process.env.ACCOUNT_NAME || "";
const key = process.env.ACCOUNT_KEY || "";
const containerName = "demo";
const blobName = "dummyfile.txt";
var strTime = new Date().toUTCString();

// read file to Stream
var filePath = `${__dirname}/README.md`;
const readStream = fs.createReadStream(filePath);
var stat = fs.statSync(filePath);

string_params = {
  verb: "PUT",
  "Content-Encoding": "",
  "Content-Language": "",
  "Content-Length": stat.size,
  "Content-MD5": "",
  "Content-Type": "application/octet-stream",
  Date: "",
  "If-Modified-Since": "",
  "If-Match": "",
  "If-None-Match": "",
  "If-Unmodified-Since": "",
  Range: "",
  CanonicalizedHeaders:
    "x-ms-blob-type:BlockBlobnx-ms-date:" +
    strTime +
    "nx-ms-version:" +
    "2020-04-08n",
  CanonicalizedResource: `/${account}/${containerName}/${blobName}`,
};

var strToSign = `${string_params["verb"]}n${string_params["Content-Encoding"]}n${string_params["Content-Language"]}n${string_params["Content-Length"]}n${string_params["Content-MD5"]}n${string_params["Content-Type"]}n${string_params["Date"]}n${string_params["If-Modified-Since"]}n${string_params["If-Match"]}n${string_params["If-None-Match"]}n${string_params["If-Unmodified-Since"]}n${string_params["Range"]}n${string_params["CanonicalizedHeaders"]}${string_params["CanonicalizedResource"]}`;

var secret = CryptoJS.enc.Base64.parse(key);
var hash = CryptoJS.HmacSHA256(strToSign, secret);
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
var auth = `SharedKey ${account}:` + hashInBase64;

const options = {
  url: `https://${account}.blob.core.windows.net/${containerName}/${blobName}`,
  headers: {
    Authorization: auth,
    "x-ms-blob-type": "BlockBlob",
    "x-ms-date": strTime,
    "x-ms-version": "2020-04-08",
    "Content-Type": "application/octet-stream",
    "Content-Length": stat.size,
  },
  body: readStream,
};

function callback(error, response, body) {
  console.log(response.statusCode);
  console.log(response.statusMessage);
  if (!error && response.statusCode == 200) {
    console.log(error);
    console.log(response);
    console.log(body);
  }
}

request.put(options, callback);

The error which I am getting is:

TypeError: Cannot read property 'statusCode' of undefined

Screenshot of error

Edit: The problem was solved by Pamela’s code + the issue I found was there’s was an error in initializing .env variables.

Answer

You could use Put Blob Rest API to upload a stream. There is a sample using node.js.

const CryptoJS = require("crypto-js");
const request = require("request");
const fs = require('fs');

const account = "account-name";
const key = "account-key";
var strTime = new Date().toUTCString();

var filePath = 'your-file-path';
const readStream = fs.createReadStream(filePath);
var stat = fs.statSync(filePath);

string_params = {
    'verb': 'PUT',
    'Content-Encoding': '',
    'Content-Language': '',
    'Content-Length': stat.size,
    'Content-MD5': '',
    'Content-Type': 'application/octet-stream',
    'Date': '',
    'If-Modified-Since': '',
    'If-Match': '',
    'If-None-Match': '',
    'If-Unmodified-Since': '',
    'Range': '',
    'CanonicalizedHeaders': 'x-ms-blob-type:BlockBlobnx-ms-date:' + strTime + 'nx-ms-version:' + '2020-04-08n',
    'CanonicalizedResource': `/${account}/containername/myblob`
}


var strToSign = `${string_params['verb']}n${string_params['Content-Encoding']}n${string_params['Content-Language']}n${string_params['Content-Length']}n${string_params['Content-MD5']}n${string_params['Content-Type']}n${string_params['Date']}n${string_params['If-Modified-Since']}n${string_params['If-Match']}n${string_params['If-None-Match']}n${string_params['If-Unmodified-Since']}n${string_params['Range']}n${string_params['CanonicalizedHeaders']}${string_params['CanonicalizedResource']}`
console.log(strToSign);

var secret = CryptoJS.enc.Base64.parse(key);
var hash = CryptoJS.HmacSHA256(strToSign, secret);
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
var auth = `SharedKey ${account}:` + hashInBase64;
console.log(auth)

const options = {
    url: `https://${account}.blob.core.windows.net/containername/myblob`,
    headers: {
        Authorization: auth,
        'x-ms-blob-type': 'BlockBlob',
        "x-ms-date": strTime,
        "x-ms-version": "2020-04-08",
        'Content-Type': "application/octet-stream",
        'Content-Length': stat.size
    },
    body: readStream
};

function callback(error, response, body) {
    console.log(response.statusCode);
    console.log(response.statusMessage);
    if (!error && response.statusCode == 200) {
        console.log(error);
        console.log(response);
        console.log(body);
    }
}

request.put(options, callback);
We are here to answer your question about Upload a Stream to Azure Blob Storage using REST API without Azure SDK - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji