import { CreateRequestOptions } from "../Data"; import { CommitChunksRequestOptionsExtended } from "../Requests/Request"; import { RequestOptionsBaseExtended } from "../Requests/RequestBase"; import { RequestFactory } from "../Requests/RequestFactory"; import { TypeOptions } from "../Sitefinity"; import { ChunkedFileUploadUtilities, ChunkFileResult } from "./chunked-file-upload.utilities"; /** * @description Entry point for all chunk upload related tasks * @export * @class ChunkUploadSdk */ export class ChunkUploadSdk { private urlOptions: TypeOptions; private factory: RequestFactory; constructor(urlOptions: TypeOptions, factory: RequestFactory) { this.urlOptions = urlOptions; this.factory = factory; } /** * @description Gets the needed information to start uploading chunks to the server * @param {GetChunkUploadInfoRequestOptions} parameters * @memberof ChunkUploadSdk */ getChunkUploadInfo(parameters: GetChunkUploadInfoRequestOptions) { Guard.isNotNull(parameters, "parameters"); Guard.isNotNull(parameters.data, "parameters.data"); Guard.isNotNull(parameters.data.libraryId, "parameters.data.libraryId"); const options: RequestOptionsBaseExtended = { urlOptions: this.urlOptions, action: `Default.GetChunkUploadInfo(libraryId=${parameters.data.libraryId})`, successCb: parameters.successCb, failureCb: parameters.failureCb, progressCb: parameters.progressCb, fallbackProperties: parameters.fallbackProperties, query: parameters.query }; const request = this.factory.get(options); request.execute(); } /** * @description Sends a single chunk request to the server * @param {UploadChunkRequestOptions} parameters * @memberof ChunkUploadSdk */ uploadChunk(parameters: UploadChunkRequestOptions) { Guard.isNotNull(parameters, "parameters"); Guard.isNotNull(parameters.data, "parameters.data"); Guard.isNotNull(parameters.data.chunkSize, "parameters.data.chunkSize"); Guard.isNotNull(parameters.data.chunkedFileUploadSessionId, "parameters.data.chunkedFileUploadSessionId"); Guard.isNotNull(parameters.data.chunkOrdinal, "parameters.data.chunkOrdinal"); Guard.isNotNull(parameters.data.numberOfChunks, "parameters.data.numberOfChunks"); Guard.isNotNull(parameters.data.chunkBlob, "parameters.data.chunkBlob"); Guard.isNotNull(parameters.data.blobStorageProviderName, "parameters.data.blobStorageProviderName"); const request = this.factory.uploadChunk({ urlOptions: this.urlOptions, fileMimeType: parameters.data.fileMimeType, chunkSize: parameters.data.chunkSize, chunkedFileUploadSessionId: parameters.data.chunkedFileUploadSessionId, chunkOrdinal: parameters.data.chunkOrdinal, numberOfChunks: parameters.data.numberOfChunks, chunkBlob: parameters.data.chunkBlob, blobStorageProviderName: parameters.data.blobStorageProviderName, fileName: parameters.data.fileName, // optional positionOfChunkInQueue: parameters.data.positionOfChunkInQueue, successCb: parameters.successCb, failureCb: parameters.failureCb, progressCb: parameters.progressCb, fallbackProperties: parameters.fallbackProperties, query: parameters.query }); request.execute(); } /** * @description Sends the commit chunks request to the server * @param {CommitChunksRequestOptions} parameters * @memberof ChunkUploadSdk */ commitChunks(parameters: CommitChunksRequestOptions) { Guard.isNotNull(parameters, "parameters"); Guard.isNotNull(parameters.data, "parameters.data"); Guard.isNotNull(parameters.data.chunkedFileUploadSessionId, "parameters.data.chunkedFileUploadSessionId"); Guard.isNotNull(parameters.data.name, "parameters.data.name"); Guard.isNotNull(parameters.data.uploadProperties, "parameters.data.uploadProperties"); Guard.isNotNull(parameters.data.numberOfChunks, "parameters.data.numberOfChunks"); Guard.isNotNull(parameters.data.fileTotalSize, "parameters.data.fileTotalSize"); Guard.isNotNull(parameters.data.blobStorageProviderName, "parameters.data.blobStorageProviderName"); const options: CommitChunksRequestOptionsExtended = { urlOptions: this.urlOptions, chunkedFileUploadSessionId: parameters.data.chunkedFileUploadSessionId, contentType: parameters.data.contentType, fileName: parameters.data.name, uploadProperties: parameters.data.uploadProperties, numberOfChunks: parameters.data.numberOfChunks, fileTotalSize: parameters.data.fileTotalSize, blobStorageProviderName: parameters.data.blobStorageProviderName, // Optional: used for update, can be null for create itemId: parameters.data.itemId, successCb: parameters.successCb, failureCb: parameters.failureCb, progressCb: parameters.progressCb, fallbackProperties: parameters.fallbackProperties, query: parameters.query }; const request = this.factory.commitChunks(options); request.execute(); } /** * @description This request is intended to be used when something in the chunk upload process fails to delete the sent chunks * @param {CleanUpChunksRequestOptions} parameters * @memberof ChunkUploadSdk */ cleanUpChunks(parameters: CleanUpChunksRequestOptions) { Guard.isNotNull(parameters, "parameters"); Guard.isNotNull(parameters.data, "parameters.data"); Guard.isNotNull(parameters.data.chunkedFileUploadSessionId, "parameters.data.chunkedFileUploadSessionId"); Guard.isNotNull(parameters.data.blobStorageProviderName, "parameters.data.blobStorageProviderName"); const request = this.factory.create({ urlOptions: this.urlOptions, action: "Default.CleanUpChunks", data: { chunkedFileUploadSessionId: parameters.data.chunkedFileUploadSessionId, blobStorageProviderName: parameters.data.blobStorageProviderName }, successCb: parameters.successCb, failureCb: parameters.failureCb, progressCb: parameters.progressCb, fallbackProperties: parameters.fallbackProperties, query: parameters.query }); request.execute(); } /** * Chunks the provided file. If the file is a base64 string this method will convert it to a blob and then chunk it. * * @param {(Blob | string)} file * @param {number} chunkSize * @param {string} contentTypeMime * @return {*} {ChunkFileResult} * @memberof ChunkUploadService */ chunkFile(file: Blob | string, chunkSize: number, contentTypeMime: string): ChunkFileResult { Guard.isNotNull(file, "file"); Guard.isNotNull(chunkSize, "chunkSize"); const utils = new ChunkedFileUploadUtilities(); return utils.chunkFile(file, chunkSize, contentTypeMime); } } class Guard { static isNotNull(value: T, parameterName: string) { if (typeof(value) === "number") { if (value === null || value === undefined) { Guard.throwException(parameterName); } return; } if (!value) { Guard.throwException(parameterName); } } private static throwException(parameterName) { throw `parameter ${parameterName} is required.`; } } //#region interfaces /** * @description This interface shows the minimum data needed to create a single chunk upload request * @export * @interface UploadChunkRequestOptions * @extends {CreateRequestOptions} */ export interface UploadChunkRequestOptions extends CreateRequestOptions { /** * @description the data needed to construct the request * @type {{ * fileMimeType: string; * chunkedFileUploadSessionId: string; * chunkSize: number; * chunkOrdinal: number; * numberOfChunks: number; * positionOfChunkInQueue?: number; * chunkBlob: Blob; * blobStorageProviderName: string; * }} * @memberof UploadChunkRequestOptions */ data: { /** * @description the file's mime type * @type {string} */ fileMimeType: string; /** * @description the file's name * @type {string} */ fileName: string; /** * @description the current chunk upload session Id * @type {string} */ chunkedFileUploadSessionId: string; /** * @description the chunk size in bytes * @type {number} */ chunkSize: number; /** * @description the chunk's ordinal * @type {number} */ chunkOrdinal: number; /** * @description the total number of chunks * @type {number} */ numberOfChunks: number; /** * @description Optional. The position of the chunk in the request queue, this property is used to calculate the progress of the upload * @type {number} */ positionOfChunkInQueue?: number; /** * @description The chunk data * @type {Blob} */ chunkBlob: Blob; /** * @description the target blob storage provider's name * @type {string} */ blobStorageProviderName: string; } } /** * @description This interface shows the minimum data needed to create a commit chunks request * @export * @interface CommitChunksRequestOptions * @extends {CreateRequestOptions} */ export interface CommitChunksRequestOptions extends CreateRequestOptions { /** * @description the data needed to construct the request * @type {{ * chunkedFileUploadSessionId: string; * contentType: string; * fileTotalSize: number; * numberOfChunks: number; * name: string; * blobStorageProviderName: string; * uploadProperties: { [key: string]: string }; * itemId?: string; * }} * @memberof CommitChunksRequestOptions */ data: { /** * @description the current chunk upload session Id * @type {string} */ chunkedFileUploadSessionId: string; /** * @description the file's mime type * @type {string} */ contentType: string; /** * @description the total size of the file * @type {number} */ fileTotalSize: number; /** * @description the total number of chunks * @type {number} */ numberOfChunks: number; /** * @description the file's name * @type {string} */ name: string; /** * @description the target blob storage provider's name * @type {string} */ blobStorageProviderName: string; /** * @description the properties of the uploaded file like the Title, UrlName, etc * @type {{ [key: string]: string }} */ uploadProperties: { [key: string]: string }; /** * @description Optional. Used when updating a media item, can be null when used to create a new media file. * @type {string} */ itemId?: string; } } /** * @description This interface shows the minimum data needed to create request to get the chunk upload information for the current library from the server * @export * @interface GetChunkUploadInfoRequestOptions * @extends {CreateRequestOptions} */ export interface GetChunkUploadInfoRequestOptions extends CreateRequestOptions { /** * @description the data needed to construct the request * @type {{ * libraryId: string; * }} * @memberof GetChunkUploadInfoRequestOptions */ data: { /** * @description the parent library (not folder) in which the file will be uploaded to * @type {string} */ libraryId: string; } } /** * @description This interface show the minimum data needed to create a request to delete all chunk from a chunk upload session * @export * @interface CleanUpChunksRequestOptions * @extends {CreateRequestOptions} */ export interface CleanUpChunksRequestOptions extends CreateRequestOptions { /** * @description the data needed to construct the request * @type {{ * chunkedFileUploadSessionId: string; * blobStorageProviderName: string; * }} * @memberof CleanUpChunksRequestOptions */ data: { /** * @description the current chunk upload session Id * @type {string} */ chunkedFileUploadSessionId: string; /** * @description the target blob storage provider's name * @type {string} */ blobStorageProviderName: string; } } /** * @description This is a data transfer object that shows the information provided by the getChunkUploadInfo request * @export * @interface ChunkUploadInfoDTO */ export interface ChunkUploadInfoDTO { /** * @description shows wether the current blob storage provider supports uploading in chunks * @type {boolean} * @memberof ChunkUploadInfoDTO */ ProviderSupportsChunkUpload: boolean; /** * @description the target blob storage provider's name * @type {string} * @memberof ChunkUploadInfoDTO */ BlobStorageProviderName: string; /** * @description the current chunk upload session Id * @type {string} * @memberof ChunkUploadInfoDTO */ ChunkedFileUploadSessionId: string, /** * @description the chunk size in bytes * @type {number} * @memberof ChunkUploadInfoDTO */ ChunkSize: number, /** * @description the maximum amount of time a chunk should be retired * @type {number} * @memberof ChunkUploadInfoDTO */ MaxRetryCountForChunk: number, /** * @description the maximum simultaneous requests that should be sent to the server * @type {number} * @memberof ChunkUploadInfoDTO */ MaxSimultaneousChunkUploadRequestsPerSession: number } /** * @description A DTO containing the data that the server responds with when a chunk is uploaded * @export * @interface ChunkUploadResult */ export interface ChunkUploadResult { /** * @description indicates whether the chunk has been successfully uploaded * @type {boolean} * @memberof ChunkUploadResult */ SuccessfullyUploaded: boolean, /** * @description the current chunk upload session Id * @type {string} * @memberof ChunkUploadResult */ ChunkedFileUploadSessionId: string } //#endregion