Я хочу удалить все файлы в моем хранилище 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. Но это дало мне индекс итерации.
Вы пробовали listBlobs() вместо listBlobsSegmented() ?
@GauravMantri Потому что я хотел бы сохранить контейнер. Но, возможно, сначала удалите контейнер, чем использовать создатьКонтейнерЕслиНесуществует(), это будет хороший план резервного копирования, спасибо!
@Neverever Я никогда не гарантирую, что listBlobsResult как из списокBlobs(), так и из списокBlobsSegmented() верен. Я отредактирую вопрос, чтобы показать listBlobsResult позже. Кстати, похоже, что списокBlobs() реализован только в старом SDK, но не в новом SDK, и я использую новый.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


При перечислении больших двоичных объектов есть параметр, называемый разделителем. Образец кода:
blobService.listBlobsSegmentedWithPrefix('documents',null,null,{delimiter:'/'},(error,result,response)=>{
console.info(result);
console.info(response.body.EnumerationResults.Blobs.BlobPrefix);
})
С разделителем / операция перечисления возвращает результаты из двух частей.
[ { Name: 'docx/' }, { Name: 'xlsx/' } ]Надеюсь, поможет.
Я тоже попробовал это решение. Это довольно функциональный метод, который заставляет меня узнать кое-что еще, но не решает мой вопрос напрямую. Спасибо за ответы!
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 */
}
В вашем коде есть две проблемы.
Оператор 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);
});
});
Согласно подразделу 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 Я публикую реализацию для listAll.
Если вы хотите удалить все большие двоичные объекты, почему бы вам просто не удалить контейнер больших двоичных объектов?