Uploading to Azure Blob Storage with Shared Access Signatures
I blogged a while ago about how you could create a SAS token to provide access to an Azure Storage blob container. In this post, I want to narrow in on the situation where you want to allow someone to simply upload one file to a container. We’ll see how to create the upload SAS token, and how to upload with the Azure SDK and the REST API.
Creating an Upload Shared Access Signature
The first part is pretty standard – we need a connection string for our storage account from which we can get hold of a CloudBlobContainer
for the container we want to upload to.
var connectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
storageAccountName, // your storage account name
accessKey); // your storage account access key
var storageAccount = CloudStorageAccount.Parse(connectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("my-container");
Next we need to specify the SharedAccessBlobPolicy
. We want to be able to Create
a file and Write
to it, and we also need to reserve a reasonable window of time for the file to be uploaded in.
SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(30);
sasConstraints.Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Create;
var blob = container.GetBlockBlobReference("outputfile.txt");
Console.WriteLine("{0}{1}",
blob.Uri, blob.GetSharedAccessSignature(sasConstraints));
We then get a blob reference to the filename we want to be able to write to (this file doesn’t need to exist in the container), and then we can use GetSharedAccessSignature
in combination with the blob’s Uri to get the full Uri and query string we need to be able to upload.
This results in a SAS Uri looking something like this:
https://mystorageacct.blob.core.windows.net/my-container/outputfile.txt?sv=2015-12-11&sr=b&sig=9UZXdW5eqoN7aiKqvnUo60gBAr1Y2feVNnIn2Hh2iU4%3D&se=2017-02-05T12%3A52%3A34Z&sp=cw
Uploading the Blob
So if we have this Shared Access Signature, how do we actually upload to it? Well, very simply with the Azure SDK. We just need to pass the full SAS Uri into a CloudBlockBlob
and then we can use various methods such as UploadFromFile
, UploadFromStream
or UploadFromByteArray
to write to it.
var sas = "https://mystorageacct.blob.core.windows.net/...";
var cloudBlockBlob = new CloudBlockBlob(new Uri(sas));
await cloudBlockBlob.UploadFromFileAsync(@"c:\myfile.txt");
Note that the name of the file cannot be changed from what is specified in the SAS Uri, so the caller is only able to write to this one file in your container.
If you prefer, you can use the Azure Blob storage REST API to upload the content directly:
var client = new HttpClient();
var content = new StringContent("Some content");
content.Headers.Add("x-ms-blob-type", "BlockBlob");
var response = await client.PutAsync(sas, content);
response.EnsureSuccessStatusCode();
Comments
Hi,
gopal krishna BanbhattaI am getting the error below when trying to upload a text file using a javascript library -
<error>
AuthorizationPermissionMismatch
<message>
This request is not authorized to perform this operation using this permission. RequestId:xxxxxx Time:2019-10-30T10:13:09.5858632Z
</message>
</error>
I thought of giving my container public Add | Create access, but the only place I could see this option is on the policy level which you have not used here in this example. So, is there a way I can use the existing policy to create the SAS token or giving write access at the container level.
Thanks
try including Read access - there are some scenarios in which this is needed for uploads
Mark HeathHi Mark,
Kriti PandeyI am trying to upload 800MB file using :
requests.put(sas_uri, data = open(file, 'rb')
but it is failing with - Connection aborted, OS32, EPIPE error. It has to do with the size of the file. Is there a way to upload this file?
hello, i have same problem with you. my solution is split file (you can find thousand there), upload partially, and then merge parted file by committing list of chunk`s name.
astrominionReference: https://docs.microsoft.com/...
Thanks for sharing this information. Really appreciated!
Robert SandonaIt is sad that you do not provide import/npm install statements for dependences here.
Askar Ibragimovthis is C#, not node
Mark Heathsorry. my bad.
Askar IbragimovThank you so much for this article, it help me lot.
muraliJust wondering if using SAS should be banned all the way since the signature is embedded in the url. I failed to see how this can be secure.
xf6jx5fqCan you limit the maximum upload size with this approach? How do you avoid people DoS-ing you with huge files?
Fabian SchmiedThanks a lot. It helps me a lot
Md. Masum Billah