使用nodejs和blob服务从blob存储下载子目录/目录?
Posted
技术标签:
【中文标题】使用nodejs和blob服务从blob存储下载子目录/目录?【英文标题】:download subdirectory/directory from blob storage using nodejs and blob service? 【发布时间】:2021-07-02 00:08:20 【问题描述】:我已经使用 blob 服务的 getBlobProperties() 和 createReadStream(containerName, fullPath, options) 方法实现了下载文件。现在,我正在尝试使用相同的方法在我的容器中下载目录/子目录,但它不起作用,并且抛出错误,指定的 blob 不存在。尽管我知道此错误的原因,但由于我不想循环 blob 并分别下载每个文件,我该如何克服这个问题?我要下载一个完整的文件夹。
这里是 API:
exports.getBlobChunk = function (req, res)
var userrole = utils.sanitizeStr(req.body.userrole);
var srcFilePath = utils.sanitizeStr(req.body.srcfilePath);
var fileName = utils.sanitizeStr(req.body.srcfileName);
var fullPath = srcFilePath + "/" + fileName;
var startRange = req.headers['startrange'];
var endRange = req.headers['endrange'];
genericHandler.getUserSubscMapping().then(function (results)
if (results != undefined && results != null)
var item = results[0].mapping.find(item => item.name == userrole);
var sasurl = item.sasurl;
if (sasurl == null)
res.status(500).send("Subscription mapping not configured");
return;
var host = sasurl.substring(0, sasurl.lastIndexOf("/"));
var containerName = sasurl.substring(sasurl.lastIndexOf("/"), sasurl.indexOf("?")).split("/")[1];
var saskey = sasurl.substring(sasurl.indexOf("?"), sasurl.length);
var download = item.download; // download usage
var blobService = storage.createBlobServiceWithSas(host, saskey);
blobService.getBlobProperties(containerName, fullPath, function (err, properties, status)
if (err)
res.send(502, "Error fetching file: %s", err.message);
else if (!status.isSuccessful)
res.send(404, "The file %s does not exist", fullPath);
else
var contentLength = properties.contentLength / 1024; // bytes to KB
res.header('Content-Type', "application/zip");
res.attachment(fileName);
var options =
rangeStart: startRange,
rangeEnd: endRange
;
if (startRange == 0) // update download size on first chunk
exports.updateStorageDownload(userrole, contentLength, download);
blobService.createReadStream(containerName, fullPath, options).pipe(res);
);
【问题讨论】:
【参考方案1】:Azure Blob 存储没有文件夹的概念,容器内的所有内容都被视为一个 Blob,包括文件夹。所以你不能下载带有文件夹名称的目录/子目录。
例如:
容器结构
hello.txt
...
test
test.txt
test1
data.json
您需要从目录中一个一个地下载blob文件。
const
BlobServiceClient,
StorageSharedKeyCredential,
= require("@azure/storage-blob");
// Enter your storage account name and shared key
const account = "";
const accountKey ="";
const containerName = "";
const filePath = "D:/downloads/"
// Use StorageSharedKeyCredential with storage account and account key
// StorageSharedKeyCredential is only available in Node.js runtime, not in browsers
const sharedKeyCredential = new StorageSharedKeyCredential(account, accountKey);
const blobServiceClient = new BlobServiceClient(
`https://$account.blob.core.windows.net`,
sharedKeyCredential,
);
async function listBlobs()
const containerClient = await blobServiceClient.getContainerClient(containerName);
console.log("list blobs with method listBlobsFlat");
let iter = containerClient.listBlobsFlat( prefix: "test/" );
for await (const item of iter)
console.log(`\tBlobItem: name - $item.name`);
downloadBlobToLocal(containerClient, item.name, filePath);
console.log("list blobs with method listBlobsByHierarchy");
let iter1 = containerClient.listBlobsByHierarchy("/", prefix: "test/" );
for await (const item of iter1)
if (item.kind === "prefix")
console.log(`\tBlobPrefix: $item.name`);
await listblob(containerClient, item.name);
else
console.log(`\tBlobItem: name - $item.name`);
downloadBlobToLocal(containerClient, item.name, filePath);
async function listblob(containerClient, prefix)
let iter1 = containerClient.listBlobsByHierarchy("/", prefix: prefix );
for await (const item of iter1)
if (item.kind === "prefix")
console.log(`\tBlobPrefix: $item.name`);
else
console.log(`\tBlobItem: name - $item.name`);
downloadBlobToLocal(containerClient, item.name, filePath);
async function downloadBlobToLocal(containerClient, blobName, filePath)
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const downloadBlockBlobResponse = await blockBlobClient.downloadToFile(filePath + blobName);
listBlobs().catch((err) =>
console.error("Error running sample:", err.message);
);
【讨论】:
如果我的回复有帮助,请采纳,谢谢。 嗨帕梅拉,我可以下载文件。我正在寻找解决方案来下载此代码无法解决我的问题的文件夹。 你的意思是下载空文件夹(比如我的结构中的'test')? Azure Blob 存储没有文件夹的概念。 例如,结构中test.txt
的blob 名称为test/test.txt
。 test
本身没有意义,不能下载。所以如果你想同时下载“文件夹”和文件(意味着blob),你需要下载test/test.txt
到loacl路径xxx/test/test.txt
。以上是关于使用nodejs和blob服务从blob存储下载子目录/目录?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Nodejs 将文件从 Azure 存储 blob(容器)复制到 Azure 文件共享
如何将所有格式的excel文件上传/下载到azure blob存储Nodejs服务器端
(Azure 存储 - nodeJS)获取应用于 blob 容器和队列的 SAS 策略
JavaScript Azure Blob 存储移动 blob