UNPKG

imago-azure-storage

Version:

An opinionated async wrapper for azure-storage for working with Azure Storage such as tables and queues.

182 lines (161 loc) 5.43 kB
const Azure = require('azure-storage'); const MemoryStream = require('memorystream'); const { readStreamAsString, stringToStream, } = require('./common'); /** * Handles CRUD operations with Azure Blob storage. * * EXAMPLE: * (to run it, the container must already be created - you can do it via * Azure Portal) (async () => { // Connect to service: const Blobs = require('./azure-blob-storage'); global.blobs = new Blobs( process.env.AZURE_STORAGE_ACCOUNT, process.env.AZURE_STORAGE_ACCESS_KEY); // Assume that the container 'my-container' is already created. let container = 'my-container'; let testContent = 'Test! ' + Date.now(); // Write file: console.log('Testing file write...'); await global.blobs.writeFile(container, 'test.txt', testContent); // Read file: console.log('Testing file read...'); let readData = await global.blobs.readFile(container, 'test.txt'); console.log('Read data: ', readData.toString('utf8')); })(); */ class AzureBlobStorage { constructor(storageAccount, storageAccessKey) { try { this.service = Azure.createBlobService(storageAccount, storageAccessKey); this.storageAccount = storageAccount; } catch (error) { console.log('Error initializing Azure Blob Storage: ', error); throw error; } } /** * Checks whether all specified containers exist, and if not, creates them. * @param {object} containers - Object containing container names and types. */ async initializeContainers(containers) { for (const container of Object.values(containers)) { console.log(`Initializing container ${container.name} in Azure storage...`); const options = {}; if (container.type === 'public') { options.publicAccessLevel = 'blob'; // has a public URL } else { // do nothing, default is private } /* eslint-disable-next-line no-await-in-loop */ await new Promise((resolve, reject) => { this.service.createContainerIfNotExists(container.name, options, (error, result) => { if (error) { reject(error); } else { resolve(result); } }); }); } } /** * Writes a file to blob. * @param {string} container - The container name. * @param {string} filename * @param {string|Buffer} content - The contents of the file to write * @returns {Promise<object>} */ writeFile(container, filename, content) { return new Promise((resolve, reject) => { const [dataStream, length] = stringToStream(content); this.service.createBlockBlobFromStream(container, filename, dataStream, length, (error, result) => { if (error) { reject(error); } else { resolve(result); } }); }); } /** * Append a string or buffer to the existing blob. * @param {string} container - The Azure blob service container name. * @param {string} filename - The name of the blob. * @param {string|Buffer} content - The contents to append (string or Buffer). */ append(container, filename, content) { return new Promise((resolve, reject) => { const [dataStream, length] = stringToStream(content); this.service.appendBlockFromStream(container, filename, dataStream, length, (error, result) => { if (error) { reject(error); } else { resolve(result); } }); }); } /** * Reads a file from Azure Blob storage and returns it as a buffer. * @param {string} container * @param {string} filename * @returns {Promise<Buffer>} The file data. */ readFile(container, filename) { return new Promise((resolve, reject) => { const writableStream = new MemoryStream(); try { const downloadedData = new Promise((resolve2, reject2) => { this.service.getBlobToStream(container, filename, writableStream, async (error) => { if (error) { reject2(error); } else { const data = await readStreamAsString(writableStream); resolve2(data); } }); }); resolve(downloadedData); } catch (outerError) { reject(outerError); } }); } /** * Checks that the specified file exists. * @param {string} container * @param {string} filename */ exists(container, filename) { return new Promise((resolve, reject) => { try { this.service.doesBlobExist(container, filename, (error, result) => { if (error) { reject(error); } else { resolve(result.exists); } }); } catch (error) { reject(error); } }); } /** * Returns a public URL for downloading a file. Will return a link even * if the container is non-public, but the link won't work. * @param {string} container * @param {anystring} filename */ getPublicDownloadLink(container, filename) { return `https://${this.storageAccount}.blob.core.windows.net/${container}/${filename}`; } } module.exports = AzureBlobStorage;