public override async Task <string> EgressAsync( AzureBlobEgressProviderOptions options, Func <CancellationToken, Task <Stream> > action, EgressArtifactSettings artifactSettings, CancellationToken token) { try { var containerClient = await GetBlobContainerClientAsync(options, token); BlobClient blobClient = containerClient.GetBlobClient(GetBlobName(options, artifactSettings)); Logger?.EgressProviderInvokeStreamAction(EgressProviderTypes.AzureBlobStorage); using var stream = await action(token); // Write blob content, headers, and metadata await blobClient.UploadAsync(stream, CreateHttpHeaders(artifactSettings), artifactSettings.Metadata, cancellationToken : token); string blobUriString = GetBlobUri(blobClient); Logger?.EgressProviderSavedStream(EgressProviderTypes.AzureBlobStorage, blobUriString); return(blobUriString); } catch (AggregateException ex) when(ex.InnerException is RequestFailedException innerException) { throw CreateException(innerException); } catch (RequestFailedException ex) { throw CreateException(ex); } }
private BlobHttpHeaders CreateHttpHeaders(EgressArtifactSettings artifactSettings) { BlobHttpHeaders headers = new BlobHttpHeaders(); headers.ContentEncoding = artifactSettings.ContentEncoding; headers.ContentType = artifactSettings.ContentType; return(headers); }
private string GetBlobName(AzureBlobEgressProviderOptions options, EgressArtifactSettings artifactSettings) { if (string.IsNullOrEmpty(options.BlobPrefix)) { return(artifactSettings.Name); } else { return(string.Concat(options.BlobPrefix, "/", artifactSettings.Name)); } }
public override async Task <string> EgressAsync( AzureBlobEgressProviderOptions options, Func <Stream, CancellationToken, Task> action, EgressArtifactSettings artifactSettings, CancellationToken token) { try { var containerClient = await GetBlobContainerClientAsync(options, token); BlockBlobClient blobClient = containerClient.GetBlockBlobClient(GetBlobName(options, artifactSettings)); // Write blob content var bloboptions = new BlockBlobOpenWriteOptions { BufferSize = BlobStorageBufferSize, }; using (Stream blobStream = await blobClient.OpenWriteAsync(overwrite: true, options: bloboptions, cancellationToken: token)) using (AutoFlushStream flushStream = new AutoFlushStream(blobStream, BlobStorageBufferSize)) { //Azure's stream from OpenWriteAsync will do the following //1. Write the data to a local buffer //2. Once that buffer is full, stage the data remotely (this data is not considered valid yet) //3. After 4Gi of data has been staged, the data will be commited. This can be forced earlier by flushing //the stream. // Since we want the data to be readily available, we automatically flush (and therefore commit) every time we fill up the buffer. Logger?.EgressProviderInvokeStreamAction(EgressProviderTypes.AzureBlobStorage); await action(flushStream, token); await flushStream.FlushAsync(token); } // Write blob headers await blobClient.SetHttpHeadersAsync(CreateHttpHeaders(artifactSettings), cancellationToken : token); // Write blob metadata await blobClient.SetMetadataAsync(artifactSettings.Metadata, cancellationToken : token); string blobUriString = GetBlobUri(blobClient); Logger?.EgressProviderSavedStream(EgressProviderTypes.AzureBlobStorage, blobUriString); return(blobUriString); } catch (AggregateException ex) when(ex.InnerException is RequestFailedException innerException) { throw CreateException(innerException); } catch (RequestFailedException ex) { throw CreateException(ex); } }
public override async Task <string> EgressAsync( FileSystemEgressProviderOptions options, Func <Stream, CancellationToken, Task> action, EgressArtifactSettings artifactSettings, CancellationToken token) { if (!Directory.Exists(options.DirectoryPath)) { WrapException(() => Directory.CreateDirectory(options.DirectoryPath)); } string targetPath = Path.Combine(options.DirectoryPath, artifactSettings.Name); if (!string.IsNullOrEmpty(options.IntermediateDirectoryPath)) { if (!Directory.Exists(options.IntermediateDirectoryPath)) { WrapException(() => Directory.CreateDirectory(options.IntermediateDirectoryPath)); } string intermediateFilePath = null; try { int remainingAttempts = 10; bool intermediatePathExists; do { intermediateFilePath = Path.Combine(options.IntermediateDirectoryPath, Path.GetRandomFileName()); intermediatePathExists = File.Exists(intermediateFilePath); remainingAttempts--; }while (intermediatePathExists && remainingAttempts > 0); if (intermediatePathExists) { throw CreateException(string.Format(CultureInfo.CurrentCulture, Strings.ErrorMessage_EgressUnableToCreateIntermediateFile, options.IntermediateDirectoryPath)); } await WriteFileAsync(action, intermediateFilePath, token); WrapException(() => File.Move(intermediateFilePath, targetPath)); } finally { // Attempt to delete the intermediate file if it exists. try { if (File.Exists(intermediateFilePath)) { File.Delete(intermediateFilePath); } } catch (Exception) { } } } else { await WriteFileAsync(action, targetPath, token); } Logger?.EgressProviderSavedStream(EgressProviderTypes.FileSystem, targetPath); return(targetPath); }