Dev
Dev

Reputation: 662

Azure Copy blobs from one container to another in same storage account using rest api and php

I am trying to copy blob from one container to another in the same storage account. The documentation of azure rest api is not clear and does not say how to copy from source container to destination container also how to copy blobs from one storage account to another storage account.

I have tried to copy blob using the below code its throws an error saying "AuthenticationFailedServer failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature."

$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.window‌​s.net/".$sourcecontainer."/".$blobname."\n‌​x-ms-version:2015-04‌​-05";
$canonicalizedResource = "/$account_name/$destcontainername/$blobname";


$arraysign = array();
$arraysign[] = 'PUT';                     /*HTTP Verb*/  
$arraysign[] = '';                        /*Content-Encoding*/  
$arraysign[] = '';                        /*Content-Language*/  
$arraysign[] = 1;                        /*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.'/'.$containername.'/blob.png'; 

$headers = [
    'x-ms-copy-source:https://'.$account_name.'.blob.core.window‌​s.net/'.$sourcecontainer.'/'.$blobname.'',
    //"x-ms-date:{$date}",
    'x-ms-version:2015-04-05',
    'Accept:application/json;odata=nometadata',
    'Accept-Charset:UTF-8',
    'Content-Length:1',
    "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);

Upvotes: 1

Views: 2134

Answers (1)

Aaron Chen
Aaron Chen

Reputation: 9950

  • The request header x-ms-date is required. It also needs presenting in $canonicalizedHeaders.
  • If the request body is none, you can set Content-Length to 0 in request headers. Then set the Content-Length part of the $stringtosign to an empty string when using version 2015-02-21 or later.

Please try the following 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);

Upvotes: 1

Related Questions