Reputation: 376
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:
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:BlockBlob\nx-ms-date:" +
strTime +
"\nx-ms-version:" +
"2020-04-08\n",
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
Edit: The problem was solved by Pamela's code + the issue I found was there's was an error in initializing .env
variables.
Upvotes: 1
Views: 1646
Reputation: 7483
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:BlockBlob\nx-ms-date:' + strTime + '\nx-ms-version:' + '2020-04-08\n',
'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);
Upvotes: 2
Reputation: 207
You can try using Azure REST API for the Blob Operations. You can find REST API's for Blob here - Operations on Blob
The question is how are you going to handle stream upload at runtime. Azure SDK supports the stream upload. However in case of REST API, you'll need to handle that by yourself.
Uploading stream or parallel data you'll need some wrapper around this REST API Calls to achieve that
Hope you find this useful.
Upvotes: 1