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 触发器将文件复制到文件共享的主要内容,如果未能解决你的问题,请参考以下文章
将文件从 SFTP 复制到 Blob 存储时并行执行 Azure 逻辑应用
使用 epplus 从 blob 触发 azure 函数访问 excel 文件
将文件上传到 Azure Blob 存储时没有触发事件网格事件——为啥?