如何从 Blob 存储中复制文件夹?
Posted
技术标签:
【中文标题】如何从 Blob 存储中复制文件夹?【英文标题】:How to copy folders from blob storage? 【发布时间】:2021-06-15 14:50:48 【问题描述】:我试图实现的功能是将粘贴文件/文件夹从一个源复制到另一个(相同的容器)。我可以使用与复制文件相同的方法来复制文件夹吗? startcopyblob() 在复制粘贴文件夹时抛出错误。
输入:
newFileName:'新文件夹_copy1' 新文件路径:'603487d1e966a91fd86b6c11/spe9_rs_2021-03-17_17-14-38/输出' oldFilePath:'603487d1e966a91fd86b6c11/spe9_rs_2021-02-23_11-14-41/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
)
..... ..
【问题讨论】:
能否告诉我 sourceContainer 和 desContainer 是否在同一个存储帐户中以及如何创建 sas 令牌? 是的,他们在同一个帐户中。我可以复制文件但对于文件夹,抛出上述错误。 是不是直接把一个文件夹复制到另一个容器里? storageuri='://host/container-name/603487d1e966a91fd86b6c11/spe9_rs_2021-02-23_11-14-41/output/new folder?sv=2019-1........ ....3D' blobname='603487d1e966a91fd86b6c11/spe9_rs_2021-03-17_17-14-38/output/new folder_copy1' 我用的是node js,,blob服务。 【参考方案1】: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 实现。更多详情请参考here和here
例如
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();
【讨论】:
以上是关于如何从 Blob 存储中复制文件夹?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Nodejs 将文件从 Azure 存储 blob(容器)复制到 Azure 文件共享
将文件从 SFTP 复制到 Blob 存储时并行执行 Azure 逻辑应用