Azure 函数 Blob 触发器将文件复制到文件共享

Posted

技术标签:

【中文标题】Azure 函数 Blob 触发器将文件复制到文件共享【英文标题】:Azure Function Blob Trigger copy file to File Share 【发布时间】:2021-11-11 21:38:06 【问题描述】:

寻求有关如何在使用 Azure 函数 Blob 触发器 (v3) 时将文件从 Azure Blob 存储复制到文件共享的帮助

我看到很多关于从文件共享复制到 Blob 的文章和 SO 问题,但没有任何反向操作,并且尝试反转我发现的代码示例效果不太好

我想出了一个解决方案,但它并不理想,因为我认为它首先将文件下载到内存中,然后将其上传到文件共享:


        [FunctionName("MyBlobTrigger")]
        public async void Run([BlobTrigger("uploads/name", Connection = "UploadStorageAccount")]Stream myBlob, string name, ILogger log, CancellationToken cancellationToken)
        

            ShareClient share = new ShareClient(storageConnection, fileShareName);

            ShareDirectoryClient directory = share.GetRootDirectoryClient();
            ShareFileClient fileShare = directory.GetFileClient(name);

            try
            
                using (Stream stream = myBlob)
                
                    fileShare.Create(stream.Length);
                    await fileShare.UploadRangeAsync(new Azure.HttpRange(0, stream.Length), stream);
                

            
         

所以这确实有效,但存在以下问题:

    我认为它是先下载到内存然后上传,宁愿只在 Azure 服务中传输文件,可能会有一些非常大的文件 我也更喜欢使用 CloudBlockBlob 而不是 Stream 作为我的 blob,主要原因是在函数结束时我需要删除文件,如果使用 CloudBlockBlob,我可以轻松地做到这一点。问题是我在使用它时无法弄清楚如何进行复制

有什么想法吗?

编辑 - 从接受的答案中使用的最终代码:

    [FunctionName("MyBlobTrigger")]
    public async void Run([BlobTrigger("uploads/name", Connection = "UploadStorageAccount")]CloudBlockBlob myBlob, string name, ILogger log, CancellationToken cancellationToken)
    

        ShareClient share = new ShareClient(storageConnection, fileShareName);

        ShareDirectoryClient directory = share.GetRootDirectoryClient();
        ShareFileClient fileShare = directory.GetFileClient(name);

        try
        

            SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy
            
                SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1),
                Permissions = SharedAccessBlobPermissions.Read
            ;
            var sasToken = myBlob.GetSharedAccessSignature(sasConstraints);
            var blobSasUrl = $"myBlob.Uri.AbsoluteUrisasToken";

            fileShare.Create(myBlob.Properties.Length);
            await fileShare.StartCopyAsync(new Uri(blobSasUrl));

【问题讨论】:

根据文档here,您应该能够提供CloudBlockBlob 类型的对象作为输入而不是流。请尝试一下。 是否有任何理由要求您使用 Azure Functions?如果您正在寻找直接的点对点副本,那么 Azure 数据工厂更合适。您可以使用内置的复制数据工具或复制活动 (more info here) 设置具有各种触发器(计划、翻转窗口、存储或自定义 - 更多信息 here)的管道,以非常轻松地实现这一目标。 @MattStannett 是的,当文件上传到 Blob 时,我需要运行它作为触发器,在复制操作之前和之后会发生一些我没有显示的处理,然后该文件最终从 blob 中删除,我无法使用数据工厂进行此处理 @GauravMantri 是的,我知道我可以使用 CloudBlockBlob 作为触发器输入,这不是我的问题,因为我更愿意使用它,问题是如何将文件从 blob 复制到文件使用 CloudBlockBlob 共享?到目前为止,我只能使用流来做到这一点 【参考方案1】:

要将 blob 的内容复制到文件共享文件,您实际上不需要先下载它。您可以简单地利用 Azure 存储的异步服务器端复制功能。

基本上,您将为具有至少read 权限的 blob 创建一个 SAS URL,然后将其用作文件复制操作的源 URL。

我在下面添加了一些伪代码来展示它是如何完成的。

[FunctionName("MyBlobTrigger")]
public async void Run([BlobTrigger("uploads/name", Connection = "UploadStorageAccount")]CloudBlockBlob myBlob, string name, ILogger log, CancellationToken cancellationToken)


    //Step 1: Get shared access signature for the blob.
    //var sasToken = myBlob.GetSharedAccessSignature();
    
    //Step 2: Get SAS URL for the blob.
    //var blobSasUrl = $"myBlob.Uri.AbsoluteUrisasToken";

    ShareClient share = new ShareClient(storageConnection, fileShareName);

    ShareDirectoryClient directory = share.GetRootDirectoryClient();
    ShareFileClient fileShare = directory.GetFileClient(name);

    ShareClient share = new ShareClient(storageConnection, fileShareName);

    ShareDirectoryClient directory = share.GetRootDirectoryClient();
    ShareFileClient fileShare = directory.GetFileClient(name);

    try
    
        //Step 3: Create empty file based on blob's content length
        //fileShare.Create(myBlob.Properties.Length);
        //Step 4: Copy blob's contents to storage file using async file copy.
        //await fileShare.StartCopyAsync(new Uri(blobSasUrl));
    

【讨论】:

谢谢,我需要为 GetSharedAccessSignature() 添加访问策略,我给它读取、列出、写入、创建 - 只是为了涵盖我的所有基础,但我在复制:“服务器未能对请求进行身份验证。确保授权标头的值格式正确,包括签名。” 我的代码只是一个伪代码。对于复制,您只需要read 权限。从错误来看,您的 SAS 令牌似乎存在问题。您可以编辑您的问题并 1) 包含您的完整代码和 2) 包含您的 SAS 令牌的外观吗? 刚刚发现问题,?构造 blobSasUrl 时不需要,因为它已经是 sas 令牌的一部分,所以我有 ??,删除了额外的,她很好,谢谢!!标记为已回答 感谢您发现问题!我已经编辑了我的答案以删除多余的?

以上是关于Azure 函数 Blob 触发器将文件复制到文件共享的主要内容,如果未能解决你的问题,请参考以下文章

子文件夹的 Azure 函数 blob 触发器

将文件从 SFTP 复制到 Blob 存储时并行执行 Azure 逻辑应用

使用 epplus 从 blob 触发 azure 函数访问 excel 文件

将文件上传到 Azure Blob 存储时没有触发事件网格事件——为啥?

将多个 Blob 输入传递给 QueueTrigger Azure 函数的最佳方式

Azure ADF 管道复制数据日志文件未触发第二个管道的“已创建 Blob”触发器