使用 Node.js 服务器为 Next.js 授权 Azure 存储服务 REST API - 从 URL 复制 Blob
Posted
技术标签:
【中文标题】使用 Node.js 服务器为 Next.js 授权 Azure 存储服务 REST API - 从 URL 复制 Blob【英文标题】:Authorization of Azure Storage service REST API for Next.js with Node.js server - Copy Blob From URL 【发布时间】:2021-12-08 14:53:26 【问题描述】:参考1:https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob-from-url
参考2:Authorization of Azure Storage service REST API
我根据上面的参考2实现了容器列表作为Next.js(/pages/api/)中的后端服务器。我在 Reference2 中实现了响应状态===OK。我的目标是使用 tier===cool 复制一个 blob,然后使用 tier===archive 将其粘贴到另一个容器中,这样我就不必在下载时更改存档 blob 的访问层。
我完全按照参考 2 进行了以下更改:
-
将 strToSign 设置为(对此部分最不确定):
const strToSign= PUT\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:$strTime\nx-ms-version:2020-10-02\n/$account/\n$containerName/$blobName
将标题(按照参考1)设置为:
const putConfig =
method: 'PUT',
headers:
'Authorization': auth,
'x-ms-date': strTime,
'x-ms-version': "2020-10-02",
'x-ms-copy-source': blobUrl,
'x-ms-requires-sync':'true'
哪里(如参考文献1),
const blobUrl = `https://$account.blob.core.windows.net/$containerName/$blobName`
fetch 是这样设置的:
fetch(https://$account.blob.core.windows.net/$containerName/$blobName
, putConfig)
.then( 结果 => console.log(results), res.end())
这是我得到的 console.log(results) 输出:
响应 大小:0, 超时:0, [符号(身体内部)]: 正文:直通 _可读状态:[可读状态], _events:[对象:空原型], _eventsCount:2, _maxListeners:未定义, _writableState:[可写状态], allowHalfOpen:真, [符号(kCapture)]:假, [符号(kCallback)]:空 , 不安:虚假, 错误:空 , [符号(响应内部)]: url: 'https://.blob.core.windows.net//', 状态:403, statusText: '服务器未能验证请求。确保 Authorization 标头的值正确形成,包括签名。', headers: Headers [Symbol(map)]: [Object: null prototype] , 计数器:0
不确定错误是什么 - 是否与在 azure 门户上的特定 blob(资源)上设置访问权限有关?你如何解决这个问题?
附言
参考3:Authentication Failed in REST api call to PUT Blob in Azure Storage [REST][Azure Blob]
我还尝试使用以下内容:
const strToSign = `PUT\n\n\n\n\n\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:$strTime\nx-ms-version:2020-10-02\n/$account/\n$containerName/\n$blobName`;
错误依旧。
【问题讨论】:
您不使用 SDK 有什么原因吗? 是的。我希望您在不更改其访问层的情况下下载存档的 Blob。如果 blob 位于存档层中,则不能将 blob 副本或来自 url 的 blob 副本与 sdk 一起使用。要重新水化存档的 blob,您需要使用 sdk 更改层,这意味着您会丢失存档的数据。如果您知道一种在不使用 sdk 更改其层的情况下复制 blob 的方法,请告诉我。欣赏! 简单的答案是你不能。为了读取存档的 blob,必须首先通过移动到热层或冷层来补充它。 【参考方案1】:根据Gaurav Matri的建议
blob 位于归档访问层,它被认为处于离线状态,无法读取或修改。
为了读取或修改存档 blob 中的数据,您必须首先将该 blob 重新水化到在线层,无论是热层还是冷层。
有两个选项可用于对存储在存档层中的 blob 进行再水化:
将存档的 Blob 复制到在线层
您可以使用 Copy Blob 或 Copy Blob from URL 操作将已归档的 Blob 复制到热层或冷层中的新 Blob 来重新水化它。 Microsoft 建议在大多数情况下使用此选项。
将 blob 的访问层更改为在线层
您可以通过使用Set Blob Tier 操作更改其层,将已归档的 blob 重新水化为热或冷。
更多详情请参考document
【讨论】:
首先,我想复制一个存档的 blob 以避免在更改层级时产生额外成本 - 这样就取消了选项 2。是的,我知道这个文档并且我阅读了它。我的理解是存档的 blob 只能通过 REST API 复制。但是,我给了 1) 一个机会:1) 我尝试了“syncCopyFromUrl”和“startCopyFromURL” 在这两种情况下,答案都是:“消息”:“在存档的 blob 上不允许此操作。”我使用的确切代码是这样的: const targetBlobClient = containerClient.getBlockBlobClient('targettest');等待 targetBlobClient.syncCopyFromURL(url); 因此,除非我对无法使用 SDK 复制存档 blob 有误(顺便说一句,如果您单击文档中的“复制 blob”和“从 url 复制 blob”链接,您将被转发到REST API 文档),我们回到最初的问题:我在原始电子邮件中的 REST API 代码有什么问题?【参考方案2】:解决方案:
const CryptoJS = require("crypto-js");
const key = "accesskey";
const version="2020-10-02"
const account = 'storagename'
const containerName = 'containername'
const strTime = (new Date()).toUTCString();
export default async (req, res) =>
if (req.method === 'POST')
const blobName = req.body
const srcBlobName = blobName
const srcBlobUrl = `https://$account.blob.core.windows.net/$containerName/$srcBlobName`
const destBlobName = srcBlobName + 'rHrH'
const destBlobUrl = `https://$account.blob.core.windows.net/$containerName/$destBlobName`;
const destAccessTier = 'Cool'
const canonicalizedHeaders = `x-ms-access-tier:$destAccessTier\nx-ms-copy-source:$srcBlobUrl\nx-ms-date:$strTime\nx-ms-version:$version\n`;
const canonicalizedResource = `/$account/$containerName/$destBlobName`;
const strToSign = `PUT\n\n\n\n\n\n\n\n\n\n\n\n$canonicalizedHeaders$canonicalizedResource`;
const secret = CryptoJS.enc.Base64.parse(key);
const hash = CryptoJS.HmacSHA256(strToSign, secret);
const hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
const auth = `SharedKey $account:`+hashInBase64;
const PUTconfig =
method: 'PUT',
headers:
'x-ms-access-tier': destAccessTier,
'x-ms-copy-source': srcBlobUrl,
'x-ms-date': strTime,
'x-ms-version': version,
'Authorization': auth
;
fetch(destBlobUrl, PUTconfig)
.then( results =>
if(results.status==200) console.log('api works') else console.log(results),
res.end()
)
【讨论】:
欢迎来到 Stack Overflow!请在您的代码中提供一些描述,以帮助读者理解您的解决方案。有关详细信息,请参阅How do I write a good answer?。 MSFT 在提示它不适合对 blob 进行再水化时删除了“从 blob url 复制”docs.microsoft.com/en-us/azure/storage/blobs/… 原因:无法设置目标 blob 的访问层以上是关于使用 Node.js 服务器为 Next.js 授权 Azure 存储服务 REST API - 从 URL 复制 Blob的主要内容,如果未能解决你的问题,请参考以下文章
如何显示从 Node.js API 发送到 Next.js 的验证错误
无法在 Next.js 应用程序中使用 Apollo-client GraphQL 上传文件:缺少 POST 正文
如何在同一个项目Node.js中将一个GAE服务列入另一个白名单