簡體   English   中英

使用nodejs和blob服務從blob存儲下載子目錄/目錄?

[英]download subdirectory/directory from blob storage using nodejs and blob service?

我已經使用 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);
}
});
}

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);
});

我根據這篇很棒的文章編寫了自己的實現:

public async Task<List<BlobDto>> ListWithPrefixAsync(string folder)
        {
            // Get a reference to a container named in appsettings.json
            BlobContainerClient container = new BlobContainerClient(_storageConnectionString, _storageContainerName);

            // Create a new list object for 
            List<BlobDto> files = new List<BlobDto>();

            await foreach (BlobItem file in container.GetBlobsAsync(prefix: folder))
            {
                // Add each file retrieved from the storage container to the files list by creating a BlobDto object
                string uri = container.Uri.ToString();
                var name = file.Name;
                var fullUri = $"{uri}/{name}";

                files.Add(new BlobDto
                {
                    Uri = fullUri,
                    Name = name,
                    ContentType = file.Properties.ContentType
                });
            }

            // Return all files to the requesting method
            return files;
        }

獲取文件夾中 blob 文件列表的實現非常簡單:

// Get all files at the Azure Storage Location and return them
        List<BlobDto>? files = await _storage.ListWithPrefixAsync(prefix);

希望這可以幫助。

編碼快樂!!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM