从未以任何格式压缩的 azure blob 存储下载文件夹

Download a folder from azure blob storage which is not compressed in any format

我正在尝试下载一个未压缩为任何格式(如 .zip、7-zip)的文件夹。我从 .

中获取了代码

我在 Azure Blob 存储上的文件夹结构就是这样 parentFolder>childFolder>1.pdf,2.pdf,3.pdf

我正在尝试下载 childFolder。我正在使用下面的代码,但出现错误 BlobNotFoundThe specified blob does not exist.

<?php

$storageAccount = 'XXXXXXX';
$containerName = 'XXXXXXX';
$blobName = 'parentFolder/childFolder';
$account_key = 'XXXXXXXXXXXXXXXXXXXXX';

$date = gmdate('D, d M Y H:i:s \G\M\T');
$version = "2019-12-12";

$stringtosign = "GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:". $date . "\nx-ms-version:".$version."\n/".$storageAccount."/".$containerName."/".$blobName;
$signature = 'SharedKey'.' '.$storageAccount.':'.base64_encode(hash_hmac('sha256', $stringtosign, base64_decode($account_key), true));
echo "\n\n" . $signature;

$header = array (
    "x-ms-date: " . $date,       
    "x-ms-version: " . $version,       
    "Authorization: " . $signature
);

$url="https://$storageAccount.blob.core.windows.net/$containerName/$blobName";
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, 'GET' );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt ( $ch, CURLOPT_HTTPHEADER, $header);
curl_exec ( $ch );
$result = curl_exec($ch);
echo "\n\n" . $result;

if(curl_errno($ch)){
    throw new Exception(curl_error($ch));
}

file_put_contents('C://demo//childFolder', $result); // save the string to a file

curl_close($ch);

您的方法行不通,因为 Azure Blob 存储中的文件夹不是真正的文件夹。它们是虚拟文件夹。您的 blob 名称是 parentFolder/childFolder/1.pdf 等等。

要从虚拟文件夹下载 blob,您需要执行以下操作:

  1. 列出 blob 容器中的 blob。由于您只想从 parentFolder/childFolder 下载 blob,因此您必须进行 prefix 搜索。这将列出所需文件夹中的所有 blob。
  2. 获得列表后,您可以从该列表下载每个 blob。

不幸的是,我对 PHP 了解不多,因此我只给你一些指导(而不是代码)。

我还建议使用 Azure Storage SDK for PHP 而不是直接使用 REST API。这将使您的工作更加轻松。您可以在此处找到有关 SDK 的更多信息:https://github.com/Azure/azure-storage-php.

只需尝试下面的代码,使用 sasTokencURL 下载文件夹下的所有 blob:

<?php 

function generateSharedAccessSignature($accountName, 
    $storageKey, 
    $signedPermissions, 
    $signedService, 
    $signedResourceType, 
    $signedStart, 
    $signedExpiry, 
    $signedIP, 
    $signedProtocol, 
    $signedVersion){

    if(empty($accountName)){
        trigger_error("The account name is required.");
        return;
    }

    if(empty($storageKey)){
        trigger_error("The account key is required.");
        return;
    }

    if(empty($signedPermissions)){
        trigger_error("The permissions are required.");
        return;
    }

    if(empty($signedService)){
        trigger_error("The services are required.");
        return;
    }

    if(empty($signedResourceType)){
        trigger_error("The resource types are required.");
        return;
    }

    if(empty($signedExpiry)){
        trigger_error("The expiration time is required.");
        return;
    }

    if(empty($signedVersion)){
        trigger_error("The service version is required.");
        return;
    }
    // generate the string to sign
    $_toSign = urldecode($accountName) . "\n" . 
            urldecode($signedPermissions) . "\n" . 
            urldecode($signedService) . "\n" . 
            urldecode($signedResourceType) . "\n" . 
            urldecode($signedStart) . "\n" .
            urldecode($signedExpiry) . "\n" .
            urldecode($signedIP) . "\n" .
            urldecode($signedProtocol) . "\n" .
            urldecode($signedVersion) . "\n";

    // sign the string using hmac sha256 and get a base64 encoded version_compare
    $_signature = base64_encode(hash_hmac("sha256", utf8_encode($_toSign), base64_decode($storageKey), true));

    return $_signature;
}

$key= "";
$storageAccount = "";
$containerName = "";
$directoryName = ""; 
$destDir = "d:/temp/";

$_signedPermissions = "rl";  //read and list permission
$_signedService = "b";       // for blob service
$_signedResourceType = "oc";  //only for access container  and object
$_signedStart = "2021-05-31T00:00:00Z";  //sas token start time
$_signedExpiry = "2021-06-10T00:00:00Z"; //sas token expairy time
$_signedIP = NULL;     // no IP limit
$_signedProtocol = "https";
$_signedVersion = "2020-02-10";

$_signature = generateSharedAccessSignature($storageAccount, 
    $key, 
    $_signedPermissions, 
    $_signedService, 
    $_signedResourceType, 
    $_signedStart, 
    $_signedExpiry, 
    $_signedIP, 
    $_signedProtocol, 
    $_signedVersion);

$sig = urlencode($_signature);

$sasToken = "sp=$_signedPermissions&srt=$_signedResourceType&ss=$_signedService&st=$_signedStart&se=$_signedExpiry&sv=$_signedVersion&spr=$_signedProtocol&sig=$sig";

$destinationURL = "https://$storageAccount.blob.core.windows.net/$containerName?restype=container&comp=list&prefix=$directoryName&$sasToken";

$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $destinationURL);

$content = curl_exec($ch);
$xml = simplexml_load_string($content);


foreach ($xml->Blobs->Blob as $i) {
    $url ="https://$storageAccount.blob.core.windows.net/$containerName/$i->Name";

    //Use basename() function to return the base name of file 
   $file_name = $destDir.basename($url)  ;
    
    //Use file_get_contents() function to get the file
    //from url and use file_put_contents() function to
    //save the file by using base name
    if(file_put_contents( $file_name,file_get_contents($url."?".$sasToken ))) {
        echo "$url:File downloaded successfully\n";
    }
    else {
        echo "File downloading failed.";
    }
}

?>

我这边测试过,结果如下: 我的斑点: