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

Posted

技术标签:

【中文标题】从未以任何格式压缩的 azure blob 存储下载文件夹【英文标题】:Download a folder from azure blob storage which is not compressed in any format 【发布时间】:2021-08-21 07:29:15 【问题描述】:

我正在尝试下载未以 .zip、7-zip 等任何格式压缩的文件夹。我从Get azure blob files from inside Sub Directories using php获取代码。

我在 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);

【问题讨论】:

请编辑您的问题并包含您编写的代码。很遗憾,您提供的信息不足以提供答案。 @GauravMantri 感谢您的建议。我更新了代码。 【参考方案1】:

只需尝试下面的代码,使用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.";
    


?>

我已经测试过了,请看下面的结果: 我的斑点:

【讨论】:

【参考方案2】:

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

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

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

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

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

【讨论】:

以上是关于从未以任何格式压缩的 azure blob 存储下载文件夹的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C# 中的 Azure.Storage.Blobs 从 Azure 存储 Blob 以 ByteArray 格式获取文件

如何在不写入文件的情况下压缩流并将其上传到 Azure Blob 存储?

使用文件流压缩文件并上传到 Azure Blob 存储

使用 ADF 将 azure blob 文件复制到 azure synapse

合并和压缩 Azure Blob 存储中的多个大文件

C# Azure.Storage.Blobs SDK 如何列出和压缩容器中的所有文件并将压缩文件存储在另一个容器中