首页 > 解决方案 > 如何从 Blob 存储中复制文件夹?

问题描述

我试图实现的功能是将粘贴文件/文件夹从一个源复制到另一个(相同的容器)。我可以使用与复制文件相同的方法来复制文件夹吗?startcopyblob() 在复制粘贴文件夹时抛出错误。

输入:

newFileName:'new folder_copy1' newFilePath:'603487d1e966a91fd86b6c11/spe9_rs_2021-03-17_17-14-38/output' oldFilePath:'603487d1e966a91fd86b6c11/spe9_rs_2021-02-23_11-14-41/output/output/

错误:

code:'CannotVerifyCopySource'
message:'The specified blob does not exist.
name:'StorageError'
requestId:'4a8a76bf-701e-0078-17c8-1b4439000000'
stack:'StorageError: The specified blob does not exist.
statusCode:404

Uncaught Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

代码:

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 blobService = storage.createBlobServiceWithSas(host, saskey);
pasteFiles.forEach(elem => {
var storageuri = host + "/" + containerName + "/" + elem["oldFilePath"] + saskey;
var blobName = elem["newFilePath"] + "/" + elem["newFileName"];
blobService.startCopyBlob(storageuri, containerName, blobName, err => {
if (err) {
console.log(err)
return res.status(500).json({
message: 'error',
status: err
})

…………

标签: node.jsazure-blob-storage

解决方案


Azure blob 存储具有 2 级层次结构 - blob 容器和 blob。它基于平面存储方案,而不是分层方案。它没有目录结构。我们只需在 blob 名称中指定字符或字符串分隔符即可创建虚拟层次结构。所以如果我们想用azure node blob sdk复制一个文件夹,我们需要将文件夹中的blob一一复制。

例如sdk

npm i @azure/storage-blob

代码

const {
  BlobServiceClient,
  StorageSharedKeyCredential,
  generateBlobSASQueryParameters,
  ContainerSASPermissions,
} = require("@azure/storage-blob");

const accountName = "andyprivate";
const accountKey =
  "";
const creds = new StorageSharedKeyCredential(accountName, accountKey);
const blobServiceClient = new BlobServiceClient(
  `https://${accountName}.blob.core.windows.net`,
  creds
);
async function test() {
  try {
    const sourceContainerClient = blobServiceClient.getContainerClient("input");
    const desContainerClient = blobServiceClient.getContainerClient("output");
    const blobSAS = generateBlobSASQueryParameters(
      {
        expiresOn: new Date(new Date().valueOf() + 86400000),
        containerName: sourceContainerClient.containerName,
        permissions: ContainerSASPermissions.parse("rl"),
      },
      creds
    ).toString();
    for await (const response of sourceContainerClient
      .listBlobsFlat({ prefix: "<your folder name>/" })
      .byPage()) {
      for (const blob of response.segment.blobItems) {
        console.log(`Blob name : ${blob.name}`);
        const sourceBlob = sourceContainerClient.getBlobClient(blob.name);
        const sourceUrl = sourceBlob.url + "?" + blobSAS;
        const res = await (
          await desContainerClient
            .getBlobClient(blob.name)
            .beginCopyFromURL(sourceUrl)
        ).pollUntilDone();

        console.log(res.copyStatus);
      }
    }
  } catch (error) {
    console.log(error);
  }
}
test();

在此处输入图像描述 在此处输入图像描述

此外,如果你想直接从另一个容器中复制一个容器中的一个文件夹,我们可以使用 azcopy 实现它。有关更多详细信息,请参阅此处此处

例如

npm i @azure/storage-blob @azure-tools/azcopy-node @azure-tools/azcopy-<your system win32 linux win64>
 

代码

const {
  StorageSharedKeyCredential,
  generateAccountSASQueryParameters,
  AccountSASPermissions,
  AccountSASResourceTypes,
  AccountSASServices,
} = require("@azure/storage-blob");

const accountName = "andyprivate";
const accountKey =
  "";
const creds = new StorageSharedKeyCredential(accountName, accountKey);
//create account sas token
const accountSas = generateAccountSASQueryParameters(
  {
    startsOn: new Date(new Date().valueOf() - 8640),
    expiresOn: new Date(new Date().valueOf() + 86400000),
    resourceTypes: AccountSASResourceTypes.parse("sco").toString(),
    permissions: AccountSASPermissions.parse("rwdlacup").toString(),
    services: AccountSASServices.parse("b").toString(),
  },
  creds
).toString();
const { AzCopyClient } = require("@azure-tools/azcopy-node");
let copyClient = new AzCopyClient();

async function copy() {


  try {
    let jobId = await copyClient.copy(
      {
        type: "RemoteSas",
        resourceUri: "https://<>.blob.core.windows.net/input",
        sasToken: accountSas,
        path: "/<folder name>",
      },
      {
        type: "RemoteSas",
        resourceUri: "https://<>.blob.core.windows.net/outcontainer",
        sasToken: accountSas,
        path: "",
      },
      { recursive: true }
    );
    let status;
    while (!status || status.StatusType !== "EndOfJob") {
      let jobInfo = await copyClient.getJobInfo(jobId);
      status = jobInfo.latestStatus;
      await new Promise((resolve, reject) => setTimeout(resolve, 1000));
    }
    console.log("OK");
  } catch (error) {
    console.log(error);
  }
}

copy();

在此处输入图像描述 在此处输入图像描述


推荐阅读