Specify Content-Type for BlockBlob upload (#3119)

* add content-type to block blob upload

* Add content-type for sdk path

* fix spacing

* merge headers and only when file extension is .txt

* add conditions

* tweak conditions and path matching

* pass in headers

* add content-type for appendblob
This commit is contained in:
Bethany
2024-02-05 13:19:02 -05:00
committed by GitHub
parent 1d82031a2c
commit bf0e76631b

View File

@@ -222,14 +222,34 @@ namespace GitHub.Services.Results.Client
return new AppendBlobClient(blobUri.path, new AzureSasCredential(blobUri.sas), opts); return new AppendBlobClient(blobUri.path, new AzureSasCredential(blobUri.sas), opts);
} }
private async Task UploadBlockFileAsync(string url, string blobStorageType, FileStream file, CancellationToken cancellationToken) private async Task UploadBlockFileAsync(string url, string blobStorageType, FileStream file, CancellationToken cancellationToken, Dictionary<string, string> customHeaders = null)
{ {
if (m_useSdk && blobStorageType == BlobStorageTypes.AzureBlobStorage) if (m_useSdk && blobStorageType == BlobStorageTypes.AzureBlobStorage)
{ {
var blobClient = GetBlobClient(url); var blobClient = GetBlobClient(url);
var httpHeaders = new BlobHttpHeaders();
if (customHeaders != null)
{
foreach (var header in customHeaders)
{
switch (header.Key)
{
case Constants.ContentTypeHeader:
httpHeaders.ContentType = header.Value;
break;
}
}
}
try try
{ {
await blobClient.UploadAsync(file, cancellationToken); await blobClient.UploadAsync(file, new BlobUploadOptions()
{
HttpHeaders = httpHeaders,
Conditions = new BlobRequestConditions
{
IfNoneMatch = new ETag("*")
}
}, cancellationToken);
} }
catch (RequestFailedException e) catch (RequestFailedException e)
{ {
@@ -249,6 +269,14 @@ namespace GitHub.Services.Results.Client
request.Content.Headers.Add(Constants.AzureBlobTypeHeader, Constants.AzureBlockBlob); request.Content.Headers.Add(Constants.AzureBlobTypeHeader, Constants.AzureBlockBlob);
} }
if (customHeaders != null)
{
foreach (var header in customHeaders)
{
request.Content.Headers.Add(header.Key, header.Value);
}
};
using (var response = await SendAsync(request, HttpCompletionOption.ResponseHeadersRead, userState: null, cancellationToken)) using (var response = await SendAsync(request, HttpCompletionOption.ResponseHeadersRead, userState: null, cancellationToken))
{ {
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
@@ -259,14 +287,34 @@ namespace GitHub.Services.Results.Client
} }
} }
private async Task CreateAppendFileAsync(string url, string blobStorageType, CancellationToken cancellationToken) private async Task CreateAppendFileAsync(string url, string blobStorageType, CancellationToken cancellationToken, Dictionary<string, string> customHeaders = null)
{ {
if (m_useSdk && blobStorageType == BlobStorageTypes.AzureBlobStorage) if (m_useSdk && blobStorageType == BlobStorageTypes.AzureBlobStorage)
{ {
var appendBlobClient = GetAppendBlobClient(url); var appendBlobClient = GetAppendBlobClient(url);
var httpHeaders = new BlobHttpHeaders();
if (customHeaders != null)
{
foreach (var header in customHeaders)
{
switch (header.Key)
{
case Constants.ContentTypeHeader:
httpHeaders.ContentType = header.Value;
break;
}
}
}
try try
{ {
await appendBlobClient.CreateAsync(cancellationToken: cancellationToken); await appendBlobClient.CreateAsync(new AppendBlobCreateOptions()
{
HttpHeaders = httpHeaders,
Conditions = new AppendBlobRequestConditions
{
IfNoneMatch = new ETag("*")
}
}, cancellationToken: cancellationToken);
} }
catch (RequestFailedException e) catch (RequestFailedException e)
{ {
@@ -284,6 +332,13 @@ namespace GitHub.Services.Results.Client
request.Content.Headers.Add(Constants.AzureBlobTypeHeader, Constants.AzureAppendBlob); request.Content.Headers.Add(Constants.AzureBlobTypeHeader, Constants.AzureAppendBlob);
request.Content.Headers.Add("Content-Length", "0"); request.Content.Headers.Add("Content-Length", "0");
} }
if (customHeaders != null)
{
foreach (var header in customHeaders)
{
request.Content.Headers.Add(header.Key, header.Value);
}
};
using (var response = await SendAsync(request, HttpCompletionOption.ResponseHeadersRead, userState: null, cancellationToken)) using (var response = await SendAsync(request, HttpCompletionOption.ResponseHeadersRead, userState: null, cancellationToken))
{ {
@@ -366,14 +421,14 @@ namespace GitHub.Services.Results.Client
} }
private async Task UploadLogFile(string file, bool finalize, bool firstBlock, string sasUrl, string blobStorageType, private async Task UploadLogFile(string file, bool finalize, bool firstBlock, string sasUrl, string blobStorageType,
CancellationToken cancellationToken) CancellationToken cancellationToken, Dictionary<string, string> customHeaders = null)
{ {
if (firstBlock && finalize) if (firstBlock && finalize)
{ {
// This is the one and only block, just use a block blob // This is the one and only block, just use a block blob
using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true)) using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
{ {
await UploadBlockFileAsync(sasUrl, blobStorageType, fileStream, cancellationToken); await UploadBlockFileAsync(sasUrl, blobStorageType, fileStream, cancellationToken, customHeaders);
} }
} }
else else
@@ -382,7 +437,7 @@ namespace GitHub.Services.Results.Client
// Create the Append blob // Create the Append blob
if (firstBlock) if (firstBlock)
{ {
await CreateAppendFileAsync(sasUrl, blobStorageType, cancellationToken); await CreateAppendFileAsync(sasUrl, blobStorageType, cancellationToken, customHeaders);
} }
// Upload content // Upload content
@@ -404,7 +459,12 @@ namespace GitHub.Services.Results.Client
throw new Exception("Failed to get step log upload url"); throw new Exception("Failed to get step log upload url");
} }
await UploadLogFile(file, finalize, firstBlock, uploadUrlResponse.LogsUrl, uploadUrlResponse.BlobStorageType, cancellationToken); var customHeaders = new Dictionary<string, string>
{
{ Constants.ContentTypeHeader, Constants.TextPlainContentType }
};
await UploadLogFile(file, finalize, firstBlock, uploadUrlResponse.LogsUrl, uploadUrlResponse.BlobStorageType, cancellationToken, customHeaders);
// Update metadata // Update metadata
if (finalize) if (finalize)
@@ -424,7 +484,12 @@ namespace GitHub.Services.Results.Client
throw new Exception("Failed to get job log upload url"); throw new Exception("Failed to get job log upload url");
} }
await UploadLogFile(file, finalize, firstBlock, uploadUrlResponse.LogsUrl, uploadUrlResponse.BlobStorageType, cancellationToken); var customHeaders = new Dictionary<string, string>
{
{ Constants.ContentTypeHeader, Constants.TextPlainContentType }
};
await UploadLogFile(file, finalize, firstBlock, uploadUrlResponse.LogsUrl, uploadUrlResponse.BlobStorageType, cancellationToken, customHeaders);
// Update metadata // Update metadata
if (finalize) if (finalize)
@@ -547,6 +612,9 @@ namespace GitHub.Services.Results.Client
public static readonly string AzureBlobTypeHeader = "x-ms-blob-type"; public static readonly string AzureBlobTypeHeader = "x-ms-blob-type";
public static readonly string AzureBlockBlob = "BlockBlob"; public static readonly string AzureBlockBlob = "BlockBlob";
public static readonly string AzureAppendBlob = "AppendBlob"; public static readonly string AzureAppendBlob = "AppendBlob";
public const string ContentTypeHeader = "Content-Type";
public const string TextPlainContentType = "text/plain";
} }
} }