private async Task CreateBlobAsync(IntuneAppPackage package, MobileAppContentFile contentFile) { var blockCount = 0; var blockIds = new List <string>(); const int chunkSize = 5 * 1024 * 1024; package.Data.Seek(0, SeekOrigin.Begin); var lastBlockId = (Math.Ceiling((double)package.Data.Length / chunkSize) - 1).ToString("0000"); foreach (var chunk in Chunk(package.Data, chunkSize, false)) { var blockId = blockCount++.ToString("0000"); logger.LogInformation($"Uploading block {blockId} of {lastBlockId} to {contentFile.AzureStorageUri}."); await using (var ms = new MemoryStream(chunk)) { await TryPutBlockAsync(contentFile, blockId, ms); } blockIds.Add(blockId); } await new CloudBlockBlob(new Uri(contentFile.AzureStorageUri)).PutBlockListAsync(blockIds); }
private async Task CreateBlobAsync(IntuneAppPackage package, MobileAppContentFile contentFile, IMobileAppContentFileRequestBuilder contentFileRequestBuilder) { var blockCount = 0; var blockIds = new List <string>(); const int chunkSize = 25 * 1024 * 1024; package.Data.Seek(0, SeekOrigin.Begin); var lastBlockId = (Math.Ceiling((double)package.Data.Length / chunkSize) - 1).ToString("0000"); var sw = Stopwatch.StartNew(); foreach (var chunk in Chunk(package.Data, chunkSize, false)) { if (sw.ElapsedMilliseconds >= 450000) { contentFile = await RenewStorageUri(contentFileRequestBuilder); sw.Restart(); } var blockId = blockCount++.ToString("0000"); logger.LogInformation($"Uploading block {blockId} of {lastBlockId} to {contentFile.AzureStorageUri}."); await using (var ms = new MemoryStream(chunk)) { try { await TryPutBlockAsync(contentFile, blockId, ms); } catch (StorageException ex) when(ex.RequestInformation.HttpStatusCode == 403) { // normally the timer should account for renewing upload URIs, but the Intune APIs are fundamentally unstable and sometimes 403s will be encountered randomly contentFile = await RenewStorageUri(contentFileRequestBuilder); sw.Restart(); await TryPutBlockAsync(contentFile, blockId, ms); } } blockIds.Add(blockId); } await new CloudBlockBlob(new Uri(contentFile.AzureStorageUri)).PutBlockListAsync(blockIds); }
private static async Task TryPutBlockAsync(MobileAppContentFile contentFile, string blockId, Stream stream) { var attemptCount = 0; var position = stream.Position; while (true) { try { await new CloudBlockBlob(new Uri(contentFile.AzureStorageUri)).PutBlockAsync(blockId, stream, null); break; } catch (StorageException ex) { if (!new[] { 307, 403, 400 }.Contains(ex.RequestInformation.HttpStatusCode) || attemptCount++ > 30) { throw; } stream.Position = position; await Task.Delay(10000); } } }
private async Task TryPutBlockAsync(MobileAppContentFile contentFile, string blockId, Stream stream) { var attemptCount = 0; var position = stream.Position; while (true) { try { await new CloudBlockBlob(new Uri(contentFile.AzureStorageUri)).PutBlockAsync(blockId, stream, null); break; } catch (StorageException ex) { if (!new[] { 307, 403, 400 }.Contains(ex.RequestInformation.HttpStatusCode) || attemptCount++ > 50) { throw; } logger.LogInformation($"Encountered retryable error ({ex.RequestInformation.HttpStatusCode}) uploading blob to {contentFile.AzureStorageUri} - will retry in 10 seconds."); stream.Position = position; await Task.Delay(10000); } } }