private void UploadFileToBlob(
CancellationToken cancellationToken,
Uri uri,
string name,
Stream stream,
string contentType,
string subDirectory,
FileEncryption fileEncryption,
CloudBlobClient client,
IRetryPolicy retryPolicy,
Func<string> getSharedAccessSignature,
int parallelTransferThreadCount,
bool shouldDoFileIO = true)
{
BlobTransferContext transferContext = new BlobTransferContext();
transferContext.Exceptions = new ConcurrentBag<Exception>();
try
{
ManualResetEvent uploadCompletedSignal = new ManualResetEvent(false);
BlobRequestOptions blobRequestOptions = new BlobRequestOptions
{
RetryPolicy = retryPolicy,
ServerTimeout = TimeSpan.FromSeconds(90)
};
CloudBlockBlob blob = GetCloudBlockBlob(uri, client, subDirectory, name, contentType, getSharedAccessSignature);
transferContext.Length = stream.Length;
transferContext.LocalFilePath = name;
transferContext.OnComplete = () => uploadCompletedSignal.Set();
transferContext.Blob = blob;
transferContext.FileEncryption = fileEncryption;
if (stream.Length == 0)
{
blob.UploadFromByteArray(new byte[1], 0, 0, options: blobRequestOptions);
}
else if (stream.Length < cloudBlockBlobUploadDownloadSizeLimit)
{
AccessCondition accessCondition = AccessCondition.GenerateEmptyCondition();
OperationContext operationContext = new OperationContext();
operationContext.ClientRequestID = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
byte[] fileContent = memoryStream.ToArray();
ApplyEncryptionTransform(
transferContext.FileEncryption,
Path.GetFileName(transferContext.LocalFilePath),
0,
fileContent,
Convert.ToInt32(stream.Length));
using (var uploadMemoryStream = new MemoryStream(fileContent))
{
blob.UploadFromStream(uploadMemoryStream, accessCondition: accessCondition, options: blobRequestOptions, operationContext: operationContext);
}
}
InvokeProgressCallback(transferContext, stream.Length, stream.Length);
transferContext.OnComplete();
}
else
{
int numThreads = parallelTransferThreadCount;
int blockSize = GetBlockSize(stream.Length);
transferContext.BlocksToTransfer = PrepareUploadDownloadQueue(stream.Length, blockSize, ref numThreads);
transferContext.BlocksForFileIO = new ConcurrentDictionary<int, byte[]>();
for (int i = 0; i < transferContext.BlocksToTransfer.Count(); i++)
{
transferContext.BlocksForFileIO[i] = null;
}
transferContext.BlockSize = blockSize;
transferContext.CancellationToken = cancellationToken;
transferContext.BlobRequestOptions = blobRequestOptions;
transferContext.MemoryManager = MemoryManagerFactory.GetMemoryManager(blockSize);
transferContext.Client = client;
transferContext.RetryPolicy = retryPolicy;
transferContext.GetSharedAccessSignature = getSharedAccessSignature;
transferContext.ShouldDoFileIO = shouldDoFileIO;
transferContext.BufferStreams = new ConcurrentDictionary<byte[], MemoryStream>();
transferContext.ClientRequestId = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);
transferContext.ContentType = contentType;
transferContext.BlobSubFolder = subDirectory;
transferContext.NextFileIOBlock = 0;
transferContext.PartialFileIOState = new ConcurrentDictionary<long, int>();
RunUploadLoop(transferContext, stream, numThreads);
}
}
catch (Exception e)
{
//Add the exception to the exception list.
transferContext.Exceptions.Add(e);
}
finally
{
// We should to be able to releaseunusedbuffers if memorymanager was initialized by then
if (transferContext.MemoryManager != null)
{
transferContext.MemoryManager.ReleaseUnusedBuffers();
}
//TaskCompletedCallback should be called to populate exceptions if relevant and other eventargs for the user.
TaskCompletedCallback(
cancellationToken.IsCancellationRequested,
transferContext.Exceptions != null && transferContext.Exceptions.Count > 0
? new AggregateException(transferContext.Exceptions)
: null,
BlobTransferType.Upload,
name,
uri);
}
}