Статьи

Загрузка большого файла путем разделения на блоки в хранилище BLOB-объектов Windows Azure

В этом сообщении мы увидим, как вы можете загрузить большой BLOB-объект в хранилище BLOB-объектов, используя Windows Azure SDK для PHP. Я должен заявить, что ничего не знаю о PHP и выполнил это упражнение, чтобы помочь кому-то в StackOverflow. В этом мне помогла отличная документация на веб-сайте PHP и мои знания о том, как работает REST API Windows Azure Blob Storage Service.

Во время этого процесса я понял, что время от времени весело выходить из зоны комфорта (для меня .Net)  Улыбка. Это чрезвычайно полезно, когда ты чего-то достиг.

Поскольку я постыдно пишу очень длинные посты в блоге  Улыбка, если вам интересно посмотреть окончательный код, прокрутите вниз до нижней части этого поста или перейдите к StackOverflow . В противном случае, пожалуйста, продолжайте читать  Улыбка.

Поскольку мы загружаем действительно большие файлы, процедура будет состоять в том, чтобы разбить файл на куски (блоки), загрузить эти куски и затем зафиксировать эти куски.

Начиная

Я предполагаю, что вы установили Windows Azure SDK для PHP. Если нет, вы можете скачать его здесь:  http://www.windowsazure.com/en-us/downloads/?sdk=php . Этот SDK зависит от некоторых внешних пакетов. Для этого сообщения в блоге нам нужно только установить  пакет  PEAR Http_Request2 , который вы можете скачать здесь:  http://pear.php.net/package/HTTP_Request2 .

Добавьте правильные классы

Мы просто должны убедиться, что мы ссылаемся на все классы, которые нам нужны в нашем коде

<?php 
require_once 'WindowsAzure/WindowsAzure.php';
use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;
use WindowsAzure\Blob\Models\Block;
use WindowsAzure\Blob\Models\BlobBlockType;
?>

Получите вещи Azure на месте

Это будет означать создание экземпляра класса « BlobRestProxy » в нашем коде. Для целей этого блога я загружаю файл в эмулятор хранилища.

$connectionString = "UseDevelopmentStorage=true";
$instance = ServicesBuilder::getInstance();
$blobRestProxy = $instance -> createBlobService($connectionString);
$containerName = "[mycontainer]";
$blobName = "[myblobname]";

Вот операции, которые нам нужно сделать:

Читать файл кусками

Чтобы прочитать файл в чанках, сначала определим размер чанка

define('CHUNK_SIZE', 1024*1024);//Block Size = 1 MB

Затем мы получим обработчик файла, указав имя файла и открыв файл

$handler = fopen("[full file path]", "r");

и теперь мы будем читать файл кусками

while (!feof($handler))
{
    $data = fread($handler, CHUNK_SIZE);
}
fclose($handler); 

Подготовить блоки

Перед этим я хочу упомянуть несколько вещей о блоках:

  • Файл можно разбить на пятьдесят тысяч (50000) блоков.
  • Каждому блоку должен быть присвоен уникальный идентификатор (идентификатор блока).
  • Все идентификаторы блоков должны иметь одинаковую длину. Я бы посоветовал вам прочитать мой предыдущий блог  для более подробной информации об этом.
  • При отправке в Windows Azure каждый идентификатор блока должен быть в кодировке Base64.

Исходя из этого, мы собираемся присвоить каждому блоку возрастающее целочисленное значение и, чтобы длина идентификатора блока оставалась неизменной, мы добавим его в нули, чтобы длина идентификатора блока составляла 6 символов.

$counter = 1;
$blockId = str_pad($counter, 6, "0", STR_PAD_LEFT);

Затем мы создадим экземпляр класса « Блок » и добавим туда этот идентификатор блока с типом «Uncommitted».

$block = new Block();
$block -> setBlockId(base64_encode($blockId));
$block -> setType("Uncommitted");

Затем мы добавляем этот блок в массив. Этот массив будет использоваться на последнем шаге для фиксации блоков (кусков).

$blockIds = array();
array_push($blockIds, $block);

Загрузить блоки

Теперь, когда у нас есть готовый контент, нам просто нужно загрузить его. Мы будем использовать « createBlobBlock функции» в « BlobRestProxy классе» , чтобы загрузить блок.

$blobRestProxy -> createBlobBlock($containerName, $blobName, base64_encode($blockId), $data);

Нам нужно сделать это для каждого блока, который мы хотим загрузить.

Фиксация блоков

Это последний шаг. После загрузки всех блоков нам нужно указать Windows Azure Blob Storage создать блоб, добавив все загруженные нами блоки. Мы будем использовать « commitBlobBlocks функции» снова в « BlobRestProxy класс» для фиксации блока.

$blobRestProxy -> commitBlobBlocks($containerName, $blobName, $blockIds);

Это оно! Вы должны увидеть блоб в своем хранилище блобов. Это так просто  Улыбка.

Полный код

Вот полный код:

<?php 
require_once 'WindowsAzure/WindowsAzure.php';
use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;
use WindowsAzure\Blob\Models\Block;
use WindowsAzure\Blob\Models\BlobBlockType;
define('CHUNK_SIZE', 1024*1024);//Block Size = 1 MB
try {
     
    $connectionString = "UseDevelopmentStorage=true";
    $instance = ServicesBuilder::getInstance();
    $blobRestProxy = $instance -> createBlobService($connectionString);
    $containerName = "[mycontainer]";
    $blobName = "[myblobname]";
    $handler = fopen("[full file path]", "r");
    $counter = 1;
    $blockIds = array();
    while (!feof($handler))
    {
        $blockId = str_pad($counter, 6, "0", STR_PAD_LEFT);
        $block = new Block();
        $block -> setBlockId(base64_encode($blockId));
        $block -> setType("Uncommitted");
        array_push($blockIds, $block);
        $data = fread($handler, CHUNK_SIZE);
        echo " \n ";
        echo " -----------------------------------------";
        echo " \n ";
        echo "Read " . strlen($data) . " of data from file";
        echo " \n ";
        echo " -----------------------------------------";
        echo " \n ";
        echo "Uploading block #: " . $blockId . " into blob storage. Please wait.";
        echo " \n ";
        echo " -----------------------------------------";
        echo " \n ";
        $blobRestProxy -> createBlobBlock($containerName, $blobName, base64_encode($blockId), $data);
        echo "Uploaded block: " . $blockId . " into blob storage.";
        echo " \n ";
        echo " -----------------------------------------";
        echo " \n ";
        $counter = $counter + 1;
    }
    fclose($handler); 
    echo "Now committing block list. Please wait.";
    echo " \n ";
    echo " -----------------------------------------";
    echo " \n ";
    $blobRestProxy -> commitBlobBlocks($containerName, $blobName, $blockIds);
    echo "Blob created successfully.";
}
catch(Exception $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here: 
    // http://msdn.microsoft.com/en-us/library/windowsazure/dd179439.aspx
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";
}
?>

Резюме

Как вы видели, насколько просто загрузить большой файл в хранилище BLOB-объектов с помощью PHP SDK. Я ничего не знал (и до сих пор не знаю) о PHP, но смог собрать этот код за считанные часы. Я думаю, что если вы разработчик PHP, вы сможете сделать это за считанные минуты. Я надеюсь, что вы нашли эту информацию полезной. Как всегда, если вы обнаружите какие-либо проблемы с сообщением, пожалуйста, дайте мне знать, и я исправлю это как можно скорее.