Quantcast
Channel: TechNet Blogs
Viewing all articles
Browse latest Browse all 17778

Call Copy Blob (Azure REST API) from SQL Server

$
0
0

Following my recent post Call Azure REST API from SQL Server I've received many requests about how to call the new API Copy Blob. Its description is here: http://msdn.microsoft.com/en-us/library/windowsazure/dd894037.aspx. As before, let me show you what we want to achieve:

 

We want to have a simple stored procedure to call with a storage account, a source and a destination blob (we need the shared key too).

EXEC Azure.CopyBlob '<storage>','<source container>','<source blob>','<destination container>','<destination blob>','<sharedkey>';

What we should do is to call the correct REST entity we want to create using the PUT verb. We must specify as header the source blob: x-ms-copy-source:name (don't forget to include it in the signature otherwise you'll get a very unpolite 403 forbidden!). Here is the main procedure code:

privatestatic Dictionary<string,string> _CopyPageBlob(string storageAccount,string srcCcontainer,string srcBlobName,string destContainer,string destBlobName,string sharedKey){string strCopySource =string.Format("https://{0:S}.blob.core.windows.net/{1:S}/{2:S}", storageAccount, srcCcontainer, srcBlobName);string strCopyDestination =string.Format("https://{0:S}.blob.core.windows.net/{1:S}/{2:S}", storageAccount, destContainer, destBlobName);string CanonicalizedResource ="/";
            CanonicalizedResource += storageAccount;
            CanonicalizedResource +="/"+ destContainer +"/"+ destBlobName;

            System.Net.HttpWebRequest Request =(System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(strCopyDestination);
            Request.Method ="PUT";
            Request.ContentLength =0;#region Add HTTP headersstring strDate = DateTime.UtcNow.ToString("R");

            Request.Headers.Add("x-ms-copy-source", strCopySource);
            Request.Headers.Add("x-ms-date", strDate);
            Request.Headers.Add("x-ms-version","2012-02-12");#endregionstring CanonicalizedHeader ="x-ms-copy-source:"+ strCopySource +"\n";
            CanonicalizedHeader +="x-ms-date:"+ strDate +"\n";
            CanonicalizedHeader +="x-ms-version:2012-02-12\n";string MessageSignature = Request.Method +"\n";
            MessageSignature +="\n";
            MessageSignature +="\n";
            MessageSignature += Request.ContentLength +"\n";
            MessageSignature +="\n";
            MessageSignature +="\n";
            MessageSignature +="\n";
            MessageSignature +="\n";
            MessageSignature +="\n";
            MessageSignature +="\n";
            MessageSignature +="\n";
            MessageSignature +="\n";

            MessageSignature += CanonicalizedHeader;
            MessageSignature += CanonicalizedResource;

            byte[] SignatureBytes = System.Text.Encoding.UTF8.GetBytes(MessageSignature);
            System.Security.Cryptography.HMACSHA256 SHA256 =new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(sharedKey));String AuthorizationHeader ="SharedKey "+ storageAccount +":"+ Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));
            Request.Headers.Add("Authorization", AuthorizationHeader);using(System.Net.HttpWebResponse response =(System.Net.HttpWebResponse)Request.GetResponse()){if(response.StatusCode == System.Net.HttpStatusCode.Accepted){
                    Dictionary<string,string> dRes =new Dictionary<string,string>();for(int i =0; i < response.Headers.Count; i++)
                        dRes.Add(response.Headers.GetKey(i), response.Headers.Get(i));return dRes;}elsethrownew Exception(response.ToString());}}

The wrapper SQL method is very simple then:

[SqlProcedure]publicstaticvoid CopyPageBlob(SqlString storageAccount,
            SqlString sourceCcontainer, SqlString sourceBlobName,
            SqlString destinationContainer, SqlString destinationBlobName,
            SqlString sharedKey){
            Dictionary<string,string> dRes = _CopyPageBlob(
                storageAccount.ToString(),
                sourceCcontainer.ToString(), sourceBlobName.ToString(),
                destinationContainer.ToString(), destinationBlobName.ToString(),
                sharedKey.ToString());

            PushRecordset(dRes);}

That alone should enable you to use this fantastic Azure feature. One point is to note, though: you might get the result before the copy is finished. The x-ms-copy-status header will tell you that (either success of pending); that's why we push it back to the caller in a recordset.

 

Happy coding,

Francesco Cogno

 

 


Viewing all articles
Browse latest Browse all 17778

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>