Как получить имя блоба из BlobResult []?

Я хочу удалить все файлы в моем хранилище BLOB-объектов Azure. Для этого я перечисляю все большие двоичные объекты в своем хранилище, используя списокBlobsSegmented(), а затем передаю результаты в удалитьBlobIfExists(). Но аргумент blob.name из списокBlobSegment() назначен неправильно. Как правильно получить имя блоба?

Это модель хранения:

const blobService = azure.createBlobService(accountName, accessKey, host); 
const containerName = 'container';

module.exports.listAll = () => {
    return new Promise(function(resolve, reject) {
        blobService.listBlobsSegmented(containerName, null, function(err, listBlobsResult) {
            if (err) {
                reject(err);
            } else {
                resolve(listBlobsResult);
            }
        });
    });
}

module.exports.delete = (blobName) => {
    return new Promise(function(resolve, reject) {
        blobService.deleteBlobIfExists(containerName, blobName, function(err, result) {
            if (err) {
                reject(err);
            } else {
                resolve({ message: `Block blob '${blobName}' deleted` });
            }
        })
    })
}

Вот как я их использую:

const azureStorage = require('./storage-model')

router.get('/listAll', function(req, res) {
    azureStorage.listAll().then((listBlobsResult) => {
        console.info(listBlobsResult);
        res.send(listBlobsResult);
    }).catch((err) => {
        console.info(err);
    });
});

router.get('/deleteAll', function(req, res) {
    azureStorage.listAll().then((listBlobsResult) => {
        var responseBody;
        for (blob in listBlobsResult.entries) {
            azureStorage.delete(blob.name).then((result) => {
                console.info(result);
                responseBody += result;
            }).catch((err) => {
                console.info(err);
            });
        }
        res.send(responseBody);
    }).catch((err) => {
        console.info(err);
    });
})

После этого он выдал мне сообщение об ошибке

ArgumentNullError: Required argument blob for function deleteBlobIfExists is not defined

Вот несколько ссылок от Microsoft deleteBlobIfExists()listBlobsSegmented()ListBlobsResultБлобрезультат

Я обнаружил, что blob.name возвращает только номер индекса большого двоичного объекта, но не фактическое имя большого двоичного объекта. Есть ли кто-нибудь, кто может мне помочь? Спасибо!


Вот как выглядит listBlobsResult.entries:

[ {previous blob result},
 BlobResult {
    name: 'my_container/some_picture.jpg',
    creationTime: 'Thu, 11 Jul 2019 09:33:20 GMT',
    lastModified: 'Thu, 11 Jul 2019 09:33:20 GMT',
    etag: '0x8D705A4CFCB5528',
    contentLength: '6300930',
    contentSettings:
     { contentType: 'application/octet-stream',
       contentEncoding: '',
       contentLanguage: '',
       contentMD5: 'OyHfg8c3irniQzyhtCBdrw==',
       cacheControl: '',
       contentDisposition: '' },
    blobType: 'BlockBlob',
    lease: { status: 'unlocked', state: 'available' },
    serverEncrypted: 'true' },
 {next blob result},
 ...{many others blob result}]

Я ожидаю, что смогу получить имя большого двоичного объекта из большого двоичного объекта записи в итерации по listBlobsResult.entries, используя blob.name. Но это дало мне индекс итерации.

Если вы хотите удалить все большие двоичные объекты, почему бы вам просто не удалить контейнер больших двоичных объектов?

Gaurav Mantri 12.07.2019 06:45

Вы пробовали listBlobs() вместо listBlobsSegmented() ?

Neverever 12.07.2019 06:55

@GauravMantri Потому что я хотел бы сохранить контейнер. Но, возможно, сначала удалите контейнер, чем использовать создатьКонтейнерЕслиНесуществует(), это будет хороший план резервного копирования, спасибо!

yyp 12.07.2019 07:57

@Neverever Я никогда не гарантирую, что listBlobsResult как из списокBlobs(), так и из списокBlobsSegmented() верен. Я отредактирую вопрос, чтобы показать listBlobsResult позже. Кстати, похоже, что списокBlobs() реализован только в старом SDK, но не в новом SDK, и я использую новый.

yyp 12.07.2019 07:57
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
4
968
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

При перечислении больших двоичных объектов есть параметр, называемый разделителем. Образец кода:

blobService.listBlobsSegmentedWithPrefix('documents',null,null,{delimiter:'/'},(error,result,response)=>{
    console.info(result);
    console.info(response.body.EnumerationResults.Blobs.BlobPrefix);
})

С разделителем / операция перечисления возвращает результаты из двух частей.

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

[ { Name: 'docx/' }, { Name: 'xlsx/' } ]

Надеюсь, поможет.

Я тоже попробовал это решение. Это довольно функциональный метод, который заставляет меня узнать кое-что еще, но не решает мой вопрос напрямую. Спасибо за ответы!

yyp 12.07.2019 08:32
Ответ принят как подходящий

listBlobsResult.entries относится к типу BlobResult[]

И есть два типа петли for, и очень часто люди их смешивают.

для ... в

for (let index in listBlobsResult.entries) {
    let blob = listBlobsResult.entries[index];

    /* ... do the work */
}

для ... из

for (let blob of listBlobsResult.entries) {
    /* ... do the work */
}

В вашем коде есть две проблемы.

  1. Оператор for...in в вашей функции обратного вызова router.get('/deleteAll', callback). Согласно документу MDN for...in statement, blob переменная for (blob in listBlobsResult.entries) фактически является числовым индексом для массива listBlobsResult.entries, как вы сказали, см. рисунок ниже.

    Итак, чтобы исправить это, есть два решения.

    1.1. Чтобы использовать for...of statement вместо for...in statement, просто измените ключевое слово in на of без других изменений, тогда переменная blob будет объектом BlobResult.

    for (var blob of listBlobsResult.entries) {
        azureStorage.delete(blob.name).then((result) => {
            console.info(result);
            responseBody += result;
        }).catch((err) => {
            console.info(err);
        });
    }
    

    1.2. Чтобы использовать функцию map для объекта Array, как показано на рисунке ниже из документа MDN для Array object.

    listBlobsResult.entries.map((blob) => {
        azureStorage.delete(blob.name).then((result) => {
            console.info(result);
            responseBody += result;
        }).catch((err) => {
            console.info(err);
        });
     });
    
  2. Согласно подразделу List the blobs официального документа Azure How to upload, download, and list blobs using the client library for Node.js v2, как показано на рисунке ниже, ваша функция listAll, использующая listBlobsSegmented(string, ContinuationToken, ErrorOrResult<ListBlobsResult>), просто перечисляет первые 5000 больших двоичных объектов в контейнере, передавая null в качестве значения параметра ContinuationToken, а не перечисляет все большие двоичные объекты.

    Итак, чтобы вывести список всех больших двоичных объектов, если в контейнере больше 5000 больших двоичных объектов, сначала нужно передать null, чтобы получить первые 5000 больших двоичных объектов и listBlobsResult.continuationToken, а затем передать предыдущее значение listBlobsResult.continuationToken функции listBlobsSegmented, чтобы получить следующие 5000 больших двоичных объектов, пока значение listBlobsResult.continuationToken не станет равным нулю. .


Обновление: реализация для listAll

const listBlobs = async (continuationToken) => {
    return new Promise((resolve, reject) => {
        blobService.listBlobsSegmented(containerName, continuationToken, (err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve(data)
            }
        });
    });
};

const listAll = async () => {
    first = await listBlobs(null);
    all = [].concat(first.entries)
    var continuationToken = first.continuationToken;
    while(continuationToken != null) {
        next = await listBlobs(continuationToken);
        all = all.concat(next.entries)
        continuationToken = next.continuationToken
    }
    return Promise.resolve(all);
};

(async() => {
    blobs = await listAll();
    blobs.map((result, index) => {console.info(index, result.name)})
})();

Спасибо за подробный ответ! Я скоро исправлю проблему списокBlobsSegmented().

yyp 12.07.2019 09:23

@yyp Я публикую реализацию для listAll.

Peter Pan 12.07.2019 11:10

Другие вопросы по теме