Статьи

Как использовать Azure Node SDK для просмотра BLOB-объектов

Последние пару недель мы работали над новым увлекательным проектом: совместным редактором уценок в реальном времени, работающим на сервере NodeJS , размещенным в Windows Azure (скоро вы узнаете об этом подробнее). Одна из функций этого приложения — возможность сохранять файлы .markdown на локальном диске или в хранилище BLOB-объектов Azure . Чтобы достичь этого, мы исследовали лучший способ составить список контейнеров и BLOB-объектов определенной учетной записи и перемещаться по ним, как если бы мы имели дело с иерархической структурой. Мы выяснили , что это может быть сделано, но это не так просто , и это звучит (вы должны использовать комбинацию префиксов и разделители опционов listBlobsоперации, наряду с проверкой элемента BlobPrefix, возвращенного в ответе API REST Blobs).

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

Чтобы получить доступ к хранилищу больших двоичных объектов, мы использовали Windows Azure SDK для Node.js (вы можете установить этот модуль в своем приложении узла, выполнив npm install azure). Также не забудьте установить Windows Azure SDK для Node.js, чтобы эмулировать среду Azure локально.

Основной сценарий

Это весь код, который вам нужен для того, чтобы перечислить контейнеры в вашей учетной записи хранения и показать внутри большие двоичные объекты. Поскольку все большие двоичные объекты хранятся в контейнере, необходимо выполнить два отдельных вызова: один для получения всех контейнеров в учетной записи, а другой — для получения больших двоичных объектов внутри определенного контейнера.

var azure = require('azure');

...

function Home () {
    this.blobService = azure.createBlobService();
};

Home.prototype = {
    showContainers: function (req, res) {
        var self = this;
        self.blobService.listContainers(function(err, result){
            // some code here to show the results
        });
    },
    showBlobs: function(req, res){
        var self = this;
        var containerName = req.query['containerName'];
        if (!containerName)
            self.showContainers(req, res);
        else
            self.blobService.listBlobs(containerName, function(err, result){
                // some code here to show the results
            });
    },

    ...
};

Ниже приведен пример того, что вы можете получить. В этом случае мы перечислили только имена BLOB-объектов. Обратите внимание, что операция listBlobs возвращает каждый большой двоичный объект в контейнере, используя листинг плоского большого объекта (подробнее о листинге плоского большого объекта здесь ).

В приведенном выше коде нет ничего плохого, и этого может быть достаточно для вас и ваших бизнес-потребностей (на самом деле, это будет прекрасно работать, если все ваши двоичные объекты являются дочерними элементами контейнера). Но что произойдет, если ваши контейнеры содержат большое количество больших двоичных объектов, организованных логическим способом, и вы хотите извлекать их ленивым образом? Если это тот случай, с которым вы столкнулись, продолжайте читать.

Использование каталогов подход

Вы можете отфильтровать результаты операции listBlob , установив параметры префикса и разделителя . Первый используется, как следует из его имени, для возврата только тех больших двоичных объектов, имена которых начинаются с указанного значения. Разделитель имеет две цели: пропустить из результата те большие двоичные объекты , имена которых содержат разделитель, и включить элемент BlobPrefix в тело ответа REST API . Этот элемент будет действовать как заполнитель для всех больших двоичных объектов, имена которых начинаются с одной и той же подстроки вплоть до появления разделителя, и будет использоваться для имитации иерархии каталогов (там будут перечислены папки).

var azure  = require('azure');

...

function Home () {
    this.blobService = azure.createBlobService();
};

function getFiles(collection){
    var items = [];
    for(var key in collection){
        var item = collection[key];
        var itemName = item.name.split('/')[item.name.split('/').length - 1];
        items.push({ 'text': itemName, 'classes': 'file'});
    }
    return items;
}

function getFolders(containerName, collection){
    var items = [];
    //if BlobPrefix contains one folder is a simple JSON. Otherwise is an array of JSONs
    if (collection && !collection.length){
        temp = collection;
        collection = [];
        collection.push(temp);
    }
    for(var key in collection){
        var item = collection[key];
        var itemName = item.Name.replace(/\/$/, '').split('/')[item.Name.replace(/\/$/, '').split('/').length - 1];
        items.push({ 'text': itemName, 'classes': 'folder' });
    }
    return items;
}

Home.prototype = {
    
    ...

    listBlobs: function(containerName, prefix, delimiter, callback){
        var self = this;
        self.blobService.listBlobs(containerName,{ 'prefix': prefix, 'delimiter': delimiter}, function(err, result, resultCont, response){
            if(!err){
                var files = getFiles(result);
                var folders = getFolders(containerName, response.body.Blobs.BlobPrefix);
                var childs = folders.concat(files);
                // return the childs
            }
        });
    },

    ...
};

Это то, что мы делаем в строках выше:

  • Сначала мы анализируем результат для доступа к возвращенным BLOB-объектам (вызывая getFiles).
  • Чтобы создать папки, мы анализируем элемент BlobPrefix (находится внутри тела ответа).
  • Наконец, мы объединяем эти две коллекции в одну.

Мы создали этот образец, чтобы продемонстрировать, как вы можете использовать все это в реальном сценарии. В нем показано, как правильно проанализировать JSON, возвращаемый операцией listBlobs , и как использовать эту информацию для заполнения элемента управления в представлении, например, в виде плагина jQuery Treeview .