Azure使用rest API将同一订阅中的Azure副本从一个存储帐户blob到另一个存储帐户

Azure使用rest API将同一订阅中的Azure副本从一个存储帐户blob到另一个存储帐户

问题描述:

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."
x-ms-date:$date
x-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("
", $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

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.