0

I would like to copy blob from one storage account to another storage account in the same subscription using Rest API and PHP. I am able to do a copy blob from one container to another in the same storage account using the below code

<?php    
$date = gmdate('D, d M Y H:i:s \G\M\T');
$account_name = "accname";
$destcontainername = "destcontainer";
$blobname = "blob.png";
$sourcecontainer = "sourcecontainer";    
$account_key = "asdf";

$canonicalizedHeaders = "x-ms-copy-source:https://".$account_name.".blob.core.windows.net/".$sourcecontainer."/".$blobname."\nx-ms-date:$date\nx-ms-version:2015-04-05";
$canonicalizedResource = "/$account_name/$destcontainername/$blobname";

$arraysign = array();
$arraysign[] = 'PUT';                     /*HTTP Verb*/  
$arraysign[] = '';                        /*Content-Encoding*/  
$arraysign[] = '';                        /*Content-Language*/  
$arraysign[] = '';                        /*Content-Length (include value when zero)*/  
$arraysign[] = '';                        /*Content-MD5*/  
$arraysign[] = '';                        /*Content-Type*/  
$arraysign[] = '';                        /*Date*/  
$arraysign[] = '';                        /*If-Modified-Since */  
$arraysign[] = '';                        /*If-Match*/  
$arraysign[] = '';                        /*If-None-Match*/  
$arraysign[] = '';                        /*If-Unmodified-Since*/  
$arraysign[] = '';                        /*Range*/  
$arraysign[] = $canonicalizedHeaders;     /*CanonicalizedHeaders*/
$arraysign[] = $canonicalizedResource;    /*CanonicalizedResource*/

$stringtosign = implode("\n", $arraysign);

$signature = 'SharedKey'.' '.$account_name.':'.base64_encode(hash_hmac('sha256', $stringtosign, base64_decode($account_key), true));

$endpoint = 'https://'.$account_name.'.blob.core.windows.net';
$url = $endpoint.'/'.$destcontainername.'/'.$blobname;

$headers = [
    'x-ms-copy-source:https://'.$account_name.'.blob.core.windows.net/'.$sourcecontainer.'/'.$blobname,
    "x-ms-date:{$date}",
    'x-ms-version:2015-04-05',
    'Accept:application/json;odata=nometadata',
    'Accept-Charset:UTF-8',
    'Content-Length:0',
    "Authorization:{$signature}"
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
$response  = curl_exec($ch);
echo curl_error($ch);
curl_close($ch);        

echo '<pre>';print_r($response);

I would like to know if i have to use the same copy blob rest API to accomplish it. If yes than what will be the $canonicalizedHeaders and $canonicalizedResource and resquest rest API. I am able to do copy blob from one storage account to another using the powershell command below

Start-AzureStorageBlobCopy -DestContainer $destinationContainerName -DestContext $destinationContext -SrcBlob $vhdName -Context $sourceContext -SrcContainer $sourceSAContainerName

1 Answer 1

2

You would use the same code for copying blobs across storage accounts as well. While $canonicalizedResource remain the same, you would need to include the URL of the source blob in x-ms-copy-source header in $canonicalizedHeaders.

One important thing to keep in mind is that the source blob URL that you specify in x-ms-copy-source header must be publicly accessible. What that means is that if you take that URL and paste that in browser's address bar, you should be able to access the blob. If the source blob container's ACL is Blob or Container, then you can simply specify the blob URL (https://sourceaccountname.blob.core.windows.net/sourceblobcontainer/sourceblobname) however if the source blob container's ACL is Private then you would need to create a Shared Access Signature (SAS) on the source blob with at least Read permission and use the SAS URL for this header's value.

Another thing to understand is that copying across storage accounts is an asynchronous operation. So when the code above executes successfully, the blob copy operation is queued. You must check if the copy operation has completed before deleting source blob or making any changes to that otherwise the copy operation will fail.

7
  • Thanks for the reply Gaurav. Here i am trying to copy the vhd files from the OSdisk and data disk from the source storage account to the destination storage account. Will the canonicalizedResource and canonicalizedHeaders still be the same?
    – Dev
    Commented Apr 19, 2017 at 12:58
  • Yes. Conceptually the process is the same whether you copy in the same account or acorss accounts. In both cases you will be calling Copy Blob REST API. The values will change based on what you're trying to copy and where i.e. source and target blob information. HTH. Commented Apr 19, 2017 at 13:04
  • I do not want to make my blobs publicly accessible, so in this scenario should i generate the SAS token for both the source and the destination storage account, if i am doing so than how should i be passing the SAS token in the curl headers.
    – Dev
    Commented Apr 19, 2017 at 13:24
  • You would need to create SAS URL for the source blob and include that in your 'x-ms-copy-source' header. Commented Apr 19, 2017 at 13:31
  • In fiddles request headers for copy blob operation i found this x-ms-copy-source:https://sourceSAName.blob.core.windows.net/vhds/vhdName?sv=2015-04-05&sr=b&sig=sdfdsfsfddsf&se=2017-04-27T06:55:57Z&sp=r. Here i can find few other parameters like sv, sr, se and sp. What are these parameters used for
    – Dev
    Commented Apr 20, 2017 at 7:03

Not the answer you're looking for? Browse other questions tagged or ask your own question.