/// <summary>
        /// Writes an input stream to an entry in the blob storage specified by the provided token.
        /// </summary>
        /// <param name="versionId">Content version id.</param>
        /// <param name="token">Blob token provided by a preliminary request.</param>
        /// <param name="input">The whole stream to write.</param>
        protected internal static async Task CopyFromStreamAsync(int versionId, string token, Stream input)
        {
            var tokenData = ChunkToken.Parse(token, versionId);

            try
            {
                using (var tran = SnTransaction.Begin())
                {
                    var context = await GetBlobStorageContextAsync(tokenData.FileId, true, versionId, tokenData.PropertyTypeId);

                    if (context.Provider == BuiltInProvider)
                    {
                        // Our built-in provider does not have a special stream for the case when
                        // the binary should be saved into a regular SQL varbinary column.
                        await CopyFromStreamByChunksAsync(context, input);
                    }
                    else
                    {
                        // This is the recommended way to write a stream to the binary storage.
                        using (var targetStream = context.Provider.GetStreamForWrite(context))
                            await input.CopyToAsync(targetStream);
                    }

                    tran.Commit();
                }
            }
            catch (Exception e)
            {
                throw new DataException("Error during saving binary chunk to stream.", e);
            }
        }
Exemple #2
0
        /// <summary>
        /// Gets a readonly stream that contains a blob entry in the blob storage.
        /// </summary>
        /// <param name="token">Blob token provided by a preliminary request.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        /// <returns>A Task that represents the asynchronous operation containig
        /// a readonly stream that comes from the blob storage directly.</returns>
        public static async Task <Stream> GetStreamForReadAsync(string token, CancellationToken cancellationToken)
        {
            var tokenData = ChunkToken.Parse(token);
            var context   = await GetBlobStorageContextAsync(tokenData.FileId, false, tokenData.VersionId, tokenData.PropertyTypeId, cancellationToken).ConfigureAwait(false);

            return(context.Provider.GetStreamForRead(context));
        }
Exemple #3
0
        /// <summary>
        /// Gets a readonly stream that contains a blob entry in the blob storage.
        /// </summary>
        /// <param name="token">Blob token provided by a preliminary request.</param>
        /// <returns>A readonly stream that comes from the blob storage directly.</returns>
        public static Stream GetStreamForRead(string token)
        {
            var tokenData = ChunkToken.Parse(token);
            var context   = GetBlobStorageContext(tokenData.FileId, false, tokenData.VersionId, tokenData.PropertyTypeId);

            return(context.Provider.GetStreamForRead(context));
        }
Exemple #4
0
        /// <summary>
        /// Writes an input stream to an entry in the blob storage specified by the provided token.
        /// </summary>
        /// <param name="versionId">Content version id.</param>
        /// <param name="token">Blob token provided by a preliminary request.</param>
        /// <param name="input">The whole stream to write.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        public async Task CopyFromStreamAsync(int versionId, string token, Stream input,
                                              CancellationToken cancellationToken)
        {
            var tokenData = ChunkToken.Parse(token, versionId);

            try
            {
                var context = await GetBlobStorageContextAsync(tokenData.FileId, true, versionId, tokenData.PropertyTypeId, cancellationToken).ConfigureAwait(false);

                if (context.Provider is IBuiltInBlobProvider)
                {
                    // Our built-in provider does not have a special stream for the case when
                    // the binary should be saved into a regular SQL varbinary column.
                    await CopyFromStreamByChunksAsync(context, input, cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    // This is the recommended way to write a stream to the binary storage.
                    using (var targetStream = context.Provider.GetStreamForWrite(context))
                        await input.CopyToAsync(targetStream).ConfigureAwait(false);
                }
            }
            catch (Exception e)
            {
                throw new DataException("Error during saving binary chunk to stream.", e);
            }
        }
Exemple #5
0
        /// <summary>
        /// Finalizes a chunked save operation.
        /// </summary>
        /// <param name="versionId">Content version id.</param>
        /// <param name="propertyTypeId">Binary property type id.</param>
        /// <param name="token">Blob token provided by a preliminary request.</param>
        /// <param name="fullSize">Full size (stream length) of the binary value.</param>
        /// <param name="source">Binary data containing metadata (e.g. content type).</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        /// <returns>A Task that represents the asynchronous operation.</returns>
        protected internal static Task CommitChunkAsync(int versionId, int propertyTypeId, string token, long fullSize, BinaryDataValue source,
                                                        CancellationToken cancellationToken)
        {
            var tokenData = ChunkToken.Parse(token, versionId);

            return(BlobStorageComponents.DataProvider.CommitChunkAsync(versionId, propertyTypeId, tokenData.FileId,
                                                                       fullSize, source, cancellationToken));
        }
Exemple #6
0
        /// <summary>
        /// Finalizes a chunked save operation.
        /// </summary>
        /// <param name="versionId">Content version id.</param>
        /// <param name="propertyTypeId">Binary property type id.</param>
        /// <param name="token">Blob token provided by a preliminary request.</param>
        /// <param name="fullSize">Full size (stream length) of the binary value.</param>
        /// <param name="source">Binary data containing metadata (e.g. content type).</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        /// <returns>A Task that represents the asynchronous operation.</returns>
        public async Task CommitChunkAsync(int versionId, int propertyTypeId, string token, long fullSize, BinaryDataValue source,
                                           CancellationToken cancellationToken)
        {
            var tokenData = ChunkToken.Parse(token, versionId);
            await DataProvider.CommitChunkAsync(versionId, propertyTypeId, tokenData.FileId,
                                                fullSize, source, cancellationToken);

            await DeleteOrphanedFilesAsync(cancellationToken);
        }
Exemple #7
0
        /// <summary>
        /// Writes a byte array to the blob entry specified by the provided token.
        /// </summary>
        /// <param name="versionId">Content version id.</param>
        /// <param name="token">Blob token provided by a preliminary request.</param>
        /// <param name="buffer">Byte array to write.</param>
        /// <param name="offset">Starting position.</param>
        /// <param name="fullSize">Full size of the whole stream.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        public async Task WriteChunkAsync(int versionId, string token, byte[] buffer, long offset, long fullSize,
                                          CancellationToken cancellationToken)
        {
            var tokenData = ChunkToken.Parse(token, versionId);

            try
            {
                var ctx = await GetBlobStorageContextAsync(tokenData.FileId, cancellationToken).ConfigureAwait(false);

                // must update properties because the Length contains the actual saved size but the feature needs the full size
                UpdateContextProperties(ctx, versionId, tokenData.PropertyTypeId, fullSize);

                await ctx.Provider.WriteAsync(ctx, offset, buffer, cancellationToken).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                throw new DataException("Error during saving binary chunk to stream.", ex);
            }
        }
Exemple #8
0
        /// <summary>
        /// Extracts the values stored in the token generated by the GetChunkToken method. This class
        /// is the only component that should know about the algorithm that builds the token.
        /// </summary>
        /// <param name="token">String data that will be parsed to ChunkToken instance.</param>
        /// <param name="versionId">Checks version id equality if the parameter value is greater than 0.
        /// Throws a DataException if the version ids are different.</param>
        /// <returns></returns>
        internal static ChunkToken Parse(string token, int versionId = 0)
        {
            var ids = token.Split('|').Select(int.Parse).ToArray();

            var tokenData = new ChunkToken
            {
                VersionId        = ids[0],
                PropertyTypeId   = ids[1],
                BinaryPropertyId = ids[2],
                FileId           = ids[3]
            };

            if (versionId > 0 && tokenData.VersionId != versionId)
            {
                throw new DataException("Version id and chunk token mismatch.");
            }

            return(tokenData);
        }
        /// <summary>
        /// Writes a byte array to the blob entry specified by the provided token.
        /// </summary>
        /// <param name="versionId">Content version id.</param>
        /// <param name="token">Blob token provided by a preliminary request.</param>
        /// <param name="buffer">Byte array to write.</param>
        /// <param name="offset">Starting position.</param>
        /// <param name="fullSize">Full size of the whole stream.</param>
        protected internal static async Task WriteChunkAsync(int versionId, string token, byte[] buffer, long offset, long fullSize)
        {
            var tokenData = ChunkToken.Parse(token, versionId);

            using (var tran = SnTransaction.Begin())
            {
                try
                {
                    var ctx = await GetBlobStorageContextAsync(tokenData.FileId);

                    // must update properties because the Length contains the actual saved size but the featue needs the full size
                    UpdateContextProperties(ctx, versionId, tokenData.PropertyTypeId, fullSize);

                    await ctx.Provider.WriteAsync(ctx, offset, buffer);

                    tran.Commit();
                }
                catch (Exception ex)
                {
                    throw new DataException("Error during saving binary chunk to stream.", ex);
                }
            }
        }
        /// <summary>
        /// Finalizes a chunked save operation.
        /// </summary>
        /// <param name="versionId">Content version id.</param>
        /// <param name="propertyTypeId">Binary property type id.</param>
        /// <param name="token">Blob token provided by a preliminary request.</param>
        /// <param name="fullSize">Full size (stream length) of the binary value.</param>
        /// <param name="source">Binary data containing metadata (e.g. content type).</param>
        protected internal static void CommitChunk(int versionId, int propertyTypeId, string token, long fullSize, BinaryDataValue source = null)
        {
            var tokenData = ChunkToken.Parse(token, versionId);

            BlobStorageComponents.DataProvider.CommitChunk(versionId, propertyTypeId, tokenData.FileId, fullSize, source);
        }