Cannot upload file to Azure Blob Node.js - node.js

Trying to upload a file to azure blob storage using #azure/storage-blob sdk in nodejs:
module.exports.createBlob = (blobName, containerName, blobContent) => {
return new Promise(async (resolve, reject) => {
try {
const sharedKeyCredential = await this.createSharedAccessToken(blobName, 'c')
const blobServiceClient = new BlobServiceClient(
`https://${process.env.AZURE_BLOB_ACCOUNT}.blob.core.windows.net`,
sharedKeyCredential
)
const containerClient = blobServiceClient.getContainerClient(containerName)
const blockBlobClient = containerClient.getBlockBlobClient(blobName)
const blob = await blockBlobClient.upload(blobContent, blobContent.length) // implement later
resolve(blob)
} catch (err) {
console.log(err)
reject(err)
}
})
}
module.exports.createSharedAccessToken = (blobName, permission) => {
return new Promise(async (resolve, reject) => {
const sharedKeyCredential = new StorageSharedKeyCredential(process.env.AZURE_BLOB_ACCOUNT, process.env.AZURE_BLOB_KEY)
const containerName = process.env.AZURE_CONTAINER_NAME
const startsOn = new Date()
expiresOn.setMinutes(expiresOn.getMinutes() + parseInt(autoLogoutDuration.KeyValue))
const blobSAS = generateBlobSASQueryParameters({
containerName, // Required
blobName, // Required
permissions: BlobSASPermissions.parse(permission), // Required
startsOn: startsOn, // Required
},
sharedKeyCredential // StorageSharedKeyCredential - `new StorageSharedKeyCredential(account, accountKey)`
).toString()
resolve(decodeURI(blobSAS))
})
}
It keeps throwing a "NoAuthenticationInformation" error. The same creds work for downloading an existing blob but uploading is not working no matter what I try. Any help would be appreciated.

Followed by this MS DOC , I tried to reproduce your issue ,but able to upload files into my azure blob container using Node.js without any authentication error.
As you are using shared key credential we need to have all those permissions in our portal as shown below:
Also i am using #azure/storage-blob sdk in nodejs in my package.json .
Also added #azure/storage-blob sdk in my testupload.js file
And added the below code into my testupload.js file as i have already created container i just commented the above screenshot code .
const account="testa";
const sharedKeyCredential = new StorageSharedKeyCredential("yourstorageaccountname", "your storage key connection string");
const blobServiceClient1 = new BlobServiceClient(
// When using AnonymousCredential, following url should include a valid SAS or support public access
`https://${account}.blob.core.windows.net`,
sharedKeyCredential
);
const blobnewname="example2.txt"
blobContent="hi hello";
const containerClient1 = blobServiceClient.getContainerClient("test")
const blockBlobClient1= containerClient.getBlockBlobClient(blobnewname)
const blob = blockBlobClient1.upload(blobContent, blobContent.length)
Then i can able to test and upload my files to Azure blob container
Here are screenshot for reference:
For more information please refer this MS DOC : Azure Storage samples using v12 JavaScript client libraries
UPDATE:-
As suggested by #Setanjan Roy
Alternate way:-
To get rid of this we can use new BlobServiceClient( https://${process.env.AZURE_BLOB_ACCOUNT}.blob.core.windows.net${sharedKeyCredential} )

Related

Blob downloadToFile() not downloading large files Nodejs

I have implemented ** azure blob/storage** in my project. And it works fine on smaller files but when I try to download a file more than 40 MB. it does not return from blob.downlaodToFile()
Here is my code.
Api call
exports.downloadSingle = function(req,res){
downloadService.downloadSingleFile(req.params.id).then(function (result) {
res.send(result);
})
}
Downlaod service
var filesLocalLinks = [];
const request = require('request-promise');
const fs = require('fs');
var download = require('download-file')
let promise = new Promise((resolve, reject) => {
filemodel.findOne({_id: id,cancelled: false}).exec(function(error,result){
if(error){
resolve(error);
}else{
blobDownload.downloadFile(result.blobName,result.containerName).then(function(blobResponse){
var filename = path.resolve(__dirname+'/../services/uploads/'+result.fileName);
filename = filename.replace('/myProject','');
filename = process.env.BASE_URL+'/myProject/services'+filename.split('/services')[1];
resolve({file: filename, filename: result.originalname})
}).catch(function(error){
reject(error);
})
}
})
})
let result =await promise;
return {file: result.file,filename: result.filename };
}
Blob service
let promise = new Promise(async (resolve, reject) => {
const account = process.env.BLOB_ACCOUNT;
const accountKey = process.env.BLOB_ACCOUNT_KEY;
const sharedKeyCredential = new StorageSharedKeyCredential(account, accountKey);
const blobServiceClient = new BlobServiceClient(
`https://${account}.blob.core.windows.net`,
sharedKeyCredential
);
const containerClient = blobServiceClient.getContainerClient(containerName);
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const blobClient = containerClient.getBlobClient(blobName);
var blobResponse = await blobClient.downloadToFile(blobName);
resolve(blobResponse)
})
let result =await promise;
return result;
}
In blob service, this line take too much time that the page responds page not working something var blobResponse = await blobClient.downloadToFile(blobName);
Can anyone help me
Basically the flow of code is, first it download the file to our server directory and then the user can download it. I figured it out that the code was working fine, but the issue was of the memory of our server, as we increased the memory, the issue is resolved. But it took my 2 days to figure it out
I came across that out of the blue.. but I noticed that you put blobName as a parameter of downloadToFile call, instead of the target file's name, not to mention that the line const blockBlobClient = containerClient.getBlockBlobClient(blobName); seems to be unnecessary, which suggests that you didn't look into your own code properly...

SharedKeyCredential is not a constructor - Azure Blob Storage + Nodejs

I'm trying to delete an image in my aucitonImages container, but when I execute the function from postman, I get SharedKeyCredential is not a constructor I've been following the documentation and I think I have everything setup, but I don't see what's different in my code from the docs. I appreciate any help!
app.delete("/api/removeauctionimages", upload, async (req, res, next) => {
const { ContainerURL, ServiceURL, StorageURL, SharedKeyCredential } = require("#azure/storage-blob");
const credentials = new SharedKeyCredential(process.env.AZURE_STORAGE_ACCOUNT, process.env.AZURE_STORAGE_ACCESS_KEY);
const pipeline = StorageURL.newPipeline(credentials);
const serviceURL = new ServiceURL(`https://${STORAGE_ACCOUNT_NAME}.blob.core.windows.net`, pipeline);
const containerName = "auctionImages";
const blobName = "myimage.png";
const containerURL = ContainerURL.fromServiceURL(serviceURL, containerName);
const blockBlobURL = BlockBlobURL.fromContainerURL(containerURL, blobName);
await blockBlobURL.delete(aborter)
console.log(`Block blob "${blobName}" is deleted`);
});
Based on the SDK Version 12.1.0 documentation here, looks like Microsoft changed SharedKeyCredential to StorageSharedKeyCredential.
Can you try with that?
Also, please see the samples for this version of SDK here: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript.
Here's the code I wrote using v12.1.0 of Node SDK:
const { StorageSharedKeyCredential, BlobServiceClient } = require("#azure/storage-blob");
const sharedKeyCredential = new StorageSharedKeyCredential(process.env.AZURE_STORAGE_ACCOUNT, process.env.AZURE_STORAGE_ACCESS_KEY);
const blobServiceClient = new BlobServiceClient(
`https://${process.env.AZURE_STORAGE_ACCOUNT}.blob.core.windows.net`,
sharedKeyCredential
);
const containerName = `temp`;
const blobName = 'test.png';
const containerClient = blobServiceClient.getContainerClient(containerName);
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
await blockBlobClient.delete();

I want to upload files to Blob Storage NOT AS STREAMS (Buffer, base64) BUT AS original file (jpg , png jpeg)

I am unable to find a way to upload a file not as a stream (buffer, base64) but as a file(png,jgeg,jpg) to Azure Storage Blob.
MY Stream Code is
const blobServiceClient = new BlobServiceClient(
`https://${account}.blob.core.windows.net`,
sharedKeyCredential, defaultAzureCredentials
);
createBlob = (blobName,blob)=>{
try{
async function main() {
const containerClient = blobServiceClient.getContainerClient('blue');
const content = base64_encode(blob.buffer);
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const uploadBlobResponse = await blockBlobClient.upload(content, content.length);
console.log(`Upload block blob ${blobName} successfully`, uploadBlobResponse.requestId);
return uploadBlobResponse.requestId;
}
main();
}
catch(err){
res.send(err)
}
}
function base64_encode(file) {
// read binary data
//var bitmap = fs.readFileSync(file);
// convert binary data to base64 encoded string
return file.toString('base64');
}
It seems that you were using #azure/storage-blob and your code inspired from Create a blob by uploading data to.
There is a function uploadFile of BlockBlobClient that can help to directly upload a local file to Azure Blob Storage, as the figure below.
Here is my sample code.
const { BlobServiceClient, StorageSharedKeyCredential } = require("#azure/storage-blob");
// Enter your storage account name and shared key
const account = "<your account name>";
const accountKey = "<your account key>";
// Use StorageSharedKeyCredential with storage account and account key
// StorageSharedKeyCredential is only avaiable in Node.js runtime, not in browsers
const sharedKeyCredential = new StorageSharedKeyCredential(account, accountKey);
const blobServiceClient = new BlobServiceClient(
`https://${account}.blob.core.windows.net`,
sharedKeyCredential
);
var containerName = '<your container name>';
var blobName = '<your blob name>';
const containerClient = blobServiceClient.getContainerClient(containerName);
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
var filePath = '<your local file path>';
blockBlobClient.uploadFile(filePath);
You can specify the content type in the options
await blockBlobClient.uploadStream(stream, bufferSize, maxConcurrency, {
blobHTTPHeaders: {
blobContentType: "image/jpeg"
}
})

How to access blob metadata using the Azure JavaScript SDK?

How do I read metadata for a blob in azure via the JavaScript SDK?
When I iterate the blobs returned from the specified container I see a metadata property:
But it's undefined, even though there is definitely metadata associated with the blob:
Is there something else I need to do to get the metadata to populate?
import { BlobServiceClient, SharedKeyCredential } from "#azure/storage-blob";
const account = "<redacted>";
const accountKey = "<redacted>";
const sharedKeyCredential = new SharedKeyCredential(account, accountKey);
const blobServiceClient = new BlobServiceClient(`https://${account}.blob.core.windows.net`, sharedKeyCredential);
const containerClient = blobServiceClient.getContainerClient(podcastName);
const blobs = await containerClient.listBlobsFlat({ include: ["metadata"] });
for await (const blob of blobs) {
console.log(blob.name);
//blob.metadata is undefined
}
// package.json relevant dependencies
"dependencies": {
"#azure/storage-blob": "^12.0.0-preview.2
}
// You can try this:
for await (const blob of containerClient.listBlobsFlat()) {
const blockBlobClient = containerClient.getBlockBlobClient(blob.name);
const meta = (await blockBlobClient.getProperties()).metadata;
console.log(meta);
// process metadata
}
I am assuming you have already declared blockBlobClient and containerClient.
If you haven't already declared blockBlobClient and containerClient ,then you can refer here
I test it's null, then I use getProperties() to get the metadata and it worked, you could have a try.
const containerName = "test";
const blobName = "test.txt";
let response;
let marker;
do {
response = await containerURL.listBlobFlatSegment(aborter);
marker = response.marker;
for(let blob of response.segment.blobItems) {
const url= BlockBlobURL.fromContainerURL(containerURL,blob.name);
const pro=await url.getProperties(aborter);
console.log(pro.metadata);
}
} while (marker);
You can fetch the properties for a blob with the getBlobMetadata method.
var storage = require('azure-storage');
var blobService = storage.createBlobService();
var containerName = 'your-container-name';
var blobName = 'my-awesome-blob';
blobService.getBlobMetadata(containerName, blobName, function(err, result, response) {
if (err) {
console.error("Couldn't fetch metadata for blob %s", blobName);
console.error(err);
} else if (!response.isSuccessful) {
console.error("Blob %s wasn't found container %s", blobName, containerName);
} else {
console.log("Successfully fetched metadata for blob %s", blobName);
console.log(result.metadata);
}
});
For more details, you could refer to this article.
in v12 you can retrieve metadata when listing blobs by passing the option includeMetadata: true
await containerClient.listBlobsFlat({ includeMetadata: true });
https://github.com/Azure/azure-sdk-for-js/blob/d2730549e078571df008e929f19c07aaf8f9efd9/sdk/storage/storage-blob/test/containerclient.spec.ts#L198

how to upload a file to Azure storage blob Container after getting sasQueryParameter in SDK v10 using nodejs?

I would like to have some help with uploading a file to Azure blob storage.
I actually want to be able to get SAS token from the backend for the container and want to be able to upload a file to that container using react web app.
I used this for reference, but couldn't get going.
use generateBlobSASQueryParameters function from #azure/storage-blob package.
the way I used generateBlobSASQueryParameters is :
const {
BlobSASPermissions,
SharedKeyCredential,
generateBlobSASQueryParameters,
} = require("#azure/storage-blob");
const {
STORAGE_ACCOUNT_KEY,
STORAGE_ACCOUNT_NAME,
CONTAINERS,
} = require("./Constants/blobStorage"); // get these from azure storage account
const generateSasQueryToken = () => {
const sharedKeyCredential = new SharedKeyCredential(STORAGE_ACCOUNT_NAME, STORAGE_ACCOUNT_KEY);
const permissions = BlobSASPermissions.parse("racwd");
const startDate = new Date();
const expiryDate = new Date(startDate);
expiryDate.setMinutes(startDate.getMinutes() + 100);
startDate.setMinutes(startDate.getMinutes() - 100);
const queryParams = generateBlobSASQueryParameters(
{
containerName: CONTAINERS.IMAGE,
permissions: permissions.toString(),
startTime: startDate,
expiryTime: expiryDate,
},
sharedKeyCredential,
);
return {
SAS_STRING: queryParams.toString(),
CONTAINER_NAME: CONTAINERS.IMAGE,
URL: `https://${STORAGE_ACCOUNT_NAME}.blob.core.windows.net/`,
};
};
module.exports = generateSasQueryToken;

Resources