Azure Javascript SDK 无法为具有访问层“存档”的 Blob 复制 Blob (sync/beginCopyBlobUrl)

Posted

技术标签:

【中文标题】Azure Javascript SDK 无法为具有访问层“存档”的 Blob 复制 Blob (sync/beginCopyBlobUrl)【英文标题】:Azure Javascript SDK Fails To Copy Blob (sync/beginCopyBlobUrl) for Blob with Access Tier 'Archive' 【发布时间】:2021-12-10 13:20:10 【问题描述】:

我正在使用 Node.js 和 Azure SDK v12。我想复制具有访问层==='Archive 的现有 blob。为此,我想复制 blob 并将其写入具有不同 blob 名称和更改(重新水化)访问层的同一容器。

我可以直接更改现有“存档”blob 的访问层,但这不是我的目标。我想保留访问层为“存档”的 blob,并创建一个访问层==="Cool 的新 blob " || "热"。

我正在按照文档 (https://docs.microsoft.com/en-us/azure/storage/blobs/archive-rehydrate-overview) 进行操作。

如果 blob 具有访问层==='Cool' ||,则以下代码有效'热的'。但是,对于访问层 ==='Archive' 的 blob,它会失败。

另外:我认为 SDK 的“syncCopyFromUrl”和“beginCopyFromUrl”不适用于复制访问层 ===“存档”的 blob。如果我尝试这样做,我会收到以下错误:对于“syncCopyFromUrl”,它给了我:“在存档的 blob 上不允许执行此操作。”对于“beginCopyFromUrl”,它给了我:“复制源 blob 已被修改” - 当我检查时,该 blob 没有被修改(我检查最后修改日期,它是过去的)。

如何复制存档的 blob 并将新 blob 保存在具有不同访问类型的同一容器中

const  BlobServiceClient,generateBlobSASQueryParameters, BlobSASPermissions  = require("@azure/storage-blob");

export default async (req, res) => 
    if (req.method === 'POST') 
      
      const connectionString = 'DefaultEndpointsProtocol=...'
      const containerName = 'container';

      const srcFile='filename' // this is the filename as it appears on Azure portal (i.e. the blob name)
      
      async function getSignedUrl(blobClient, options=)

          options.permissions = options.permissions || "racwd"
          const expiry = 3600;
          const startsOn = new Date();
          const expiresOn = new Date(new Date().valueOf() + expiry * 1000);
        
        
          const token = await generateBlobSASQueryParameters(
              
                  containerName: blobClient.containerName,
                  blobName: blobClient.name,
                  permissions: BlobSASPermissions.parse(options.permissions),
                  startsOn, // Required
                  expiresOn, // Optional
              ,
              blobClient.credential,
          );
      
          return `$blobClient.url?$token.toString()`;
      
      
      (async () => 
          try 
              const blobServiceClient = BlobServiceClient.fromConnectionString(connectionString);
              const containerClient = blobServiceClient.getContainerClient(containerName);
              const sourceBlobClient = containerClient.getBlockBlobClient(srcFile);
              const targetBlobClient = containerClient.getBlockBlobClient('targetFileName');
      
              const url = await getSignedUrl(sourceBlobClient);
              console.log(`source: $url`);
              
              const result = await targetBlobClient.syncCopyFromURL(url);
              // const result = await targetBlobClient.beginCopyFromURL(url);
              
              console.log(result)
           catch (e) 
              console.log(e);
          
      )();
    


export const config = 
    api: 
      bodyParser: 
        sizeLimit: '1gb',
      ,
    ,

【问题讨论】:

【参考方案1】:

我们需要知道的主要步骤是更改 blob 的访问层。

通过下面的代码,我们可以从 JS 设置访问层:

  // Archive the blob - Log the error codes
      await blockBlobClient.setAccessTier("Archive");
      try 
        // Downloading an archived blockBlob fails
        console.log("// Downloading an archived blockBlob fails...");
        await blockBlobClient.download();
       catch (err) 
        // BlobArchived Conflict (409)  This operation is not permitted on an archived blob.
        console.log(
          `requestId - $err.details.requestId, statusCode - $err.statusCode, errorCode - $err.details.errorCode`
        );
        console.log(`error message - $err.details.message\n`);
      

其余的操作可以在复制事件的帮助下完成,如下所示:

import logging
import sys
import os
import azure.functions as func
from azure.storage import blob
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient, __version__

def main(myblob: func.InputStream):
    try:
        logging.info(f"Python blob trigger function processed blob \n")
        CONN_STR = "ADD_CON_STR"
        blob_service_client = BlobServiceClient.from_connection_string(CONN_STR)

        # MAP SOURCE FILE
        blob_client = blob_service_client.get_blob_client(container="newcontainer0805", blob="source.txt")

        #SOURCE CONTENTS
        content =  blob_client.download_blob().content_as_text
        
        # WRITE HEADER TO A OUT PUTFILE
        output_file_dest = blob_service_client.get_blob_client(container="target", blob="target.csv")
        
        #INITIALIZE OUTPUT               
        output_str = ""
        
        #STORE COULMN HEADERS
        data= list()
            
        data.append(list(["column1", "column2", "column3", "column4"]))
        output_str += ('"' + '","'.join(data[0]) + '"\n')
        output_file_dest.upload_blob(output_str,overwrite=True)
        logging.info(' END OF FILE UPLOAD')
    except Exception as e:
        template = "An exception of type 0 occurred. Arguments:\n1!r"
        message = template.format(type(e).__name__, e.args)
        print (message)
if __name__ == "__main__":
    main("source.txt")

如果您想将 blob 保存在与源相同的容器修改目标容器中,这可以帮助您复制 blob 并将数据附加到其中。

【讨论】:

感谢您的评论 - 我使用 REST API 解决了这个问题 => ***.com/questions/69668784/…

以上是关于Azure Javascript SDK 无法为具有访问层“存档”的 Blob 复制 Blob (sync/beginCopyBlobUrl)的主要内容,如果未能解决你的问题,请参考以下文章

Azure Speech javascript SDK:以 mp3 格式输出音频

Azure 信息保护/权利管理服务 SDK 2.1 - 无法启用文档跟踪

Azure,java sdk,使用ARM模板部署 - 无法转换参数文件

Azure blobs Java sdk 无法返回对象的 versionID 列表

安装 Azure SDK 2.0 后无法创建云项目

如何使用 JavaScript v12 SDK for Browsers 检索和显示(在浏览器中)存储在 Azure 存储帐户中的多个 pdf 的 URL