question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] Upload (PUT) via SAS URI deletes metadata on blob.

See original GitHub issue

Library name and version

12.11.0

Describe the bug

When creating a blob via BlobClient and setting the metadata, an then obtaining a sas url with write permissions, if I use that uri to upload the blob content, the metadata on the blob is removed.

The file upload via the sas uri works correctly.

Expected behavior

The metadata remains on the blob version.

Actual behavior

the metadata is empty on the blob ( visible through code or the Azure storage Exploer/portal)

Reproduction Steps

using the following code stub to set metadata and createa sas uri. Some code ommitted for brevity.

BlobContainerClient` containerClient = new BlobContainerClient(_storageConnectionString, containerName);
var blobClient = containerClient.GetBlobClient("attachments/" + filePrefix + originalFileName);

//@see https://github.com/Azure/azure-sdk-for-net/issues/10784
if (!blobClient.Exists())
       await blobClient.UploadAsync(new System.IO.MemoryStream());

await blobClient.SetMetadataAsync(new Dictionary<string, string> { { ORIGINAL_FILENAME_METADATA_KEY, originalFileName } });
			BlobProperties properties = await blobClient.GetPropertiesAsync();
			Debug.Assert(properties.Metadata.Any(), "metadata was saved");

                var sasURI = GetServiceSasUriForBlob(blobClient, BlobSasPermissions.Write, ip);

Upload code

	private static async Task UploadFile(string sasUrl, MemoryStream file, string fileName) {

			using (var value = new ByteArrayContent(file.ToArray())) {
				value.Headers.Add("x-ms-blob-type", "BlockBlob");
				value.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
				value.Headers.Add("Content-Disposition", $"form-data; filename=\"{fileName}\"");

				// Use a raw client for blobstore and enable compression. 
				HttpClientHandler handler = new HttpClientHandler();
				if (handler.SupportsAutomaticDecompression)
					handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
				var client = new HttpClient(handler);

				var upload = await client.PutAsync(sasUrl, value);
				if (!upload.IsSuccessStatusCode) {
					throw new System.Exception("Failed to upload file : " + upload.ReasonPhrase);
				}
			}
		}

Environment

.NET SDK (reflecting any global.json): Version: 6.0.202 Commit: f8a55617d2

Runtime Environment: OS Name: Windows OS Version: 10.0.19044 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\6.0.202\

Host (useful for support): Version: 6.0.4 Commit: be98e88c76

.NET SDKs installed: 6.0.104 [C:\Program Files\dotnet\sdk] 6.0.202 [C:\Program Files\dotnet\sdk]

.NET runtimes installed: Microsoft.AspNetCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs: https://aka.ms/dotnet-download

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
markjerzcommented, Jun 22, 2022

The documentation does make it quite clear that metadata gets deleted in a PUT blob request (https://docs.microsoft.com/en-us/rest/api/storageservices/put-blob)

Like @vllama I can’t quite believe this type of feature isn’t supported. It makes a lot of sense to provide SAS uris to clients so that they can upload their files directly to storage instead of proxying them through our own web apps.

The documentation says that you can use Put Block to just upload content but the problem with that is that you then need to call Put Block List to “commit” the changed data. Obviously, that’s leaking the abstraction quite a lot to the client who was just expecting to upload a file to some URI.

The only other option is to give the metadata to the client so that they can add it to the request headers when they upload. That’s now leaky in terms of the data as well as the abstraction.

0reactions
msftbot[bot]commented, May 9, 2022

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @xgithubtriage.

Issue Details

Library name and version

12.11.0

Describe the bug

When creating a blob via BlobClient and setting the metadata, an then obtaining a sas url with write permissions, if I use that uri to upload the blob content, the metadata on the blob is removed.

The file upload via the sas uri works correctly.

Expected behavior

The metadata remains on the blob version.

Actual behavior

the metadata is empty on the blob ( visible through code or the Azure storage Exploer/portal)

Reproduction Steps

using the following code stub to set metadata and createa sas uri. Some code ommitted for brevity.

BlobContainerClient` containerClient = new BlobContainerClient(_storageConnectionString, containerName);
var blobClient = containerClient.GetBlobClient("attachments/" + filePrefix + originalFileName);

//@see https://github.com/Azure/azure-sdk-for-net/issues/10784
if (!blobClient.Exists())
       await blobClient.UploadAsync(new System.IO.MemoryStream());

await blobClient.SetMetadataAsync(new Dictionary<string, string> { { ORIGINAL_FILENAME_METADATA_KEY, originalFileName } });
			BlobProperties properties = await blobClient.GetPropertiesAsync();
			Debug.Assert(properties.Metadata.Any(), "metadata was saved");

                var sasURI = GetServiceSasUriForBlob(blobClient, BlobSasPermissions.Write, ip);

Upload code

	private static async Task UploadFile(string sasUrl, MemoryStream file, string fileName) {

			using (var value = new ByteArrayContent(file.ToArray())) {
				value.Headers.Add("x-ms-blob-type", "BlockBlob");
				value.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
				value.Headers.Add("Content-Disposition", $"form-data; filename=\"{fileName}\"");

				// Use a raw client for blobstore and enable compression. 
				HttpClientHandler handler = new HttpClientHandler();
				if (handler.SupportsAutomaticDecompression)
					handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
				var client = new HttpClient(handler);

				var upload = await client.PutAsync(sasUrl, value);
				if (!upload.IsSuccessStatusCode) {
					throw new System.Exception("Failed to upload file : " + upload.ReasonPhrase);
				}
			}
		}

Environment

.NET SDK (reflecting any global.json): Version: 6.0.202 Commit: f8a55617d2

Runtime Environment: OS Name: Windows OS Version: 10.0.19044 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\6.0.202\

Host (useful for support): Version: 6.0.4 Commit: be98e88c76

.NET SDKs installed: 6.0.104 [C:\Program Files\dotnet\sdk] 6.0.202 [C:\Program Files\dotnet\sdk]

.NET runtimes installed: Microsoft.AspNetCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs: https://aka.ms/dotnet-download

Author: vllama
Assignees: -
Labels:

Storage, Service Attention, Client, customer-reported, question, needs-team-attention

Milestone: -
Read more comments on GitHub >

github_iconTop Results From Across the Web

Put Blob (REST API) - Azure Storage
The Put Blob operation creates a new block, page, or append blob, or updates the content of an existing block blob.
Read more >
Manage properties and metadata for a blob with .NET
Learn how to set and retrieve system properties and store custom metadata on blobs in your Azure Storage account using the .
Read more >
How to create SAS token to list\delete blobs
1 Answer 1 ... So there are two things here: ... Necessary permissions for get blob list, read metadata and delete old blobs:...
Read more >
AzureStorage Blob Server failed to authenticate ...
I got an error while uploading files into Azure Blob storage with metadata, the error is "Server failed to authenticate the request. Make...
Read more >
BlockBlobClient | @azure/storage-blob
You can call commitBlockList to update a blob by uploading only those blocks that have changed, then committing the new and existing blocks...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found