src/persistence/mapiBlobStorage.ts (83 lines of code) (raw):

import { AzureBlobStorage } from "@paperbits/azure"; import { Logger } from "@paperbits/common/logging"; import { ISettingsProvider } from "@paperbits/common/configuration"; import { StaticSettingsProvider } from "../configuration/staticSettingsProvider"; import { Utils } from "../utils"; import { TenantService } from "../services/tenantService"; import { ReadStream } from "fs"; import { IStreamBlobStorage } from "./IStreamBlobStorage"; const defaultContainerName = "content"; export class MapiBlobStorage implements IStreamBlobStorage { private storageClient: AzureBlobStorage; constructor( private readonly tenantService: TenantService, private readonly settingsProvider: ISettingsProvider, private readonly logger: Logger ) { } private async getStorageClient(): Promise<AzureBlobStorage> { if (this.storageClient) { return this.storageClient; } let storageSettingsProvider: ISettingsProvider; const blobStorageContainer = await this.settingsProvider.getSetting<string>("blobStorageContainer"); const blobStorageConnectionString = await this.settingsProvider.getSetting<string>("blobStorageConnectionString"); const blobStorageUrl = await this.settingsProvider.getSetting<string>("blobStorageUrl"); if (blobStorageConnectionString) { storageSettingsProvider = new StaticSettingsProvider({ blobStorageConnectionString: blobStorageConnectionString, blobStorageContainer: blobStorageContainer || defaultContainerName }); } else if (blobStorageUrl) { const parsedUrl = new URL(blobStorageUrl); const containerSegment = blobStorageContainer ? blobStorageContainer : defaultContainerName; const normalizedBlobStorageUrl = `${parsedUrl.protocol}//${parsedUrl.hostname}${Utils.ensureLeadingSlash(containerSegment)}${parsedUrl.search}`; storageSettingsProvider = new StaticSettingsProvider({ blobStorageUrl: normalizedBlobStorageUrl }); } else { const containerSasUrl = await this.tenantService.getMediaContentBlobUrl(); storageSettingsProvider = new StaticSettingsProvider({ blobStorageUrl: containerSasUrl }); } this.storageClient = new AzureBlobStorage(storageSettingsProvider, this.logger); return this.storageClient; } /** * Lists all blobs in storage or with specific prefix (in a specific "folder"). * @param blobPrefix Blob prefix. */ public async listBlobs?(blobPrefix?: string): Promise<string[]> { const client = await this.getStorageClient(); return await client.listBlobs(blobPrefix); } /** * Uploads blob with specified key to storage. * @param blobKey Unique blob identifier. * @param content Content in form of byte array. * @param contentType Content type (MIME) of the content. */ public async uploadBlob(blobKey: string, content: Uint8Array, contentType?: string): Promise<void> { const client = await this.getStorageClient(); return await client.uploadBlob(blobKey, content, contentType); } /** * Downloads blob with specified key. * @param blobKey Unique blob identifier. */ public async downloadBlob?(blobKey: string): Promise<Uint8Array> { const client = await this.getStorageClient(); return await client.downloadBlob(blobKey); } /** * Returns download URL of uploaded blob. * @param blobKey Unique blob identifier. */ public async getDownloadUrl(blobKey: string): Promise<string> { const client = await this.getStorageClient(); return await client.getDownloadUrl(blobKey); } /** * Returns download URL of uploaded blob without token. * @param blobKey Unique blob identifier. */ public async getDownloadUrlWithoutToken(blobKey: string): Promise<string> { const url = new URL(await this.getDownloadUrl(blobKey)); ["sv", "st", "se", "sr", "sp", "sig"].forEach(key => url.searchParams.delete(key)); return url.toString(); } /** * Removes specified blob from memory. * @param blobKey Unique blob identifier. */ public async deleteBlob(blobKey: string): Promise<void> { const client = await this.getStorageClient(); return await client.deleteBlob(blobKey); } /** * Uploads specified content into storage in Node.JS * @param blobKey {string} Blob key. * @param content {ReadStream} Content stream. * @param contentType {string} Content type, e.g. `image/png`. */ public async uploadStreamToBlob(blobKey: string, contentStream: ReadStream, contentType?: string): Promise<void> { const client = await this.getStorageClient(); await client.uploadStreamToBlob(blobKey, contentStream, contentType); } /** * Get blob from storage in Node.JS * @param blobKey {string} Blob key. */ public async getBlobAsStream(blobKey: string): Promise<NodeJS.ReadableStream> { const client = await this.getStorageClient(); return client.getBlobAsStream(blobKey); } }