Azure Function中Azure Blob Storage文件解密后上传的实现问题
Azure Function Blob流解密上传问题
我正在开发一个Azure Function App,需从Azure Blob Storage获取.pgp文件,解密后将解密后的文件重新上传回Blob Storage。现有资料大多假设将文件下载到本地驱动器后再解密上传,但我希望全程在Azure环境中通过流处理完成,无需本地存储。
目前已编写部分代码,可成功连接并将文件下载到流中,但不知如何正确关联输入流与输出流。其中UploadAsync()方法的调用存在问题,该方法需要传入参数,但我误以为targetBlobClient已包含Blob容器和文件名的引用,找不到相关示例解决问题。
原错误代码片段
var outputStream = await targetBlobClient.UploadAsync();
完整原代码
try { var privateKeyValue = GetKeyVaultSecretValue(m.KeyVaultURL, m.KeyVaultPrivateSecretName); var privateKeyPassword = GetKeyVaultSecretValue(m.KeyVaultURL, m.KeyVaultPrivateSecretPassword); var storageConnString = m.InputStorageConnection; var containerName = m.InputStorageContainer; var sourceFile = m.InputFileName; var targetFile = m.OutputFileName; var sourceFolder = Path.Combine(m.InputStorageContainer, m.InputStorageFolder); var targetFolder = Path.Combine(m.OutputStorageContainer, m.OutputFolder); Console.WriteLine(@"Source full path: " + sourceFolder + "\\" + sourceFile); BlobServiceClient blobServiceClient = new BlobServiceClient(storageConnString); BlobContainerClient sourceContainerClient = blobServiceClient.GetBlobContainerClient(sourceFolder); BlobClient sourceBlobClient = sourceContainerClient.GetBlobClient(sourceFile); BlobContainerClient targetContainerClient = blobServiceClient.GetBlobContainerClient(targetFolder); BlobClient targetBlobClient = sourceContainerClient.GetBlobClient(targetFile); if (await sourceBlobClient.ExistsAsync()) { var inputStream = await sourceBlobClient.DownloadAsync(); var outputStream = await targetBlobClient.UploadAsync(); EncryptionKeys encryptionKeys = new EncryptionKeys(privateKeyValue, privateKeyPassword); PGP pgp = new PGP(encryptionKeys); await pgp.DecryptStreamAsync(inputStream, outputStream); } else { Console.WriteLine(@"Error finding file. " + sourceFolder + "\\" + sourceFile); _log.LogError("Error find file {0}\\{1}.", sourceFolder, sourceFile); } } catch (Exception ex) { _log.LogError("Error decrypting file. EventType: {0} | File: {1} | {2} | {3} | {4}", m.EventName, m.InputFileName, ex.Message, ex.StackTrace, ex.InnerException); Console.WriteLine("Error: " + ex.Message); }
问题修正与解决方案
核心问题点
UploadAsync方法使用错误:BlobClient的UploadAsync必须接收要上传的流作为参数,无法无参获取输出流直接写入;需先通过内存流承接解密后的内容,再上传,或者使用上传时的流写入模式。- 目标BlobClient指向错误:原代码中
targetBlobClient从sourceContainerClient获取,会导致文件上传到源容器,需改为从targetContainerClient获取。 - 输入流处理错误:
DownloadAsync()返回的是BlobDownloadInfo对象,需提取其Content属性作为实际输入流。
修正后的完整代码
try { var privateKeyValue = GetKeyVaultSecretValue(m.KeyVaultURL, m.KeyVaultPrivateSecretName); var privateKeyPassword = GetKeyVaultSecretValue(m.KeyVaultURL, m.KeyVaultPrivateSecretPassword); var storageConnString = m.InputStorageConnection; var sourceFile = m.InputFileName; var targetFile = m.OutputFileName; var sourceFolder = Path.Combine(m.InputStorageContainer, m.InputStorageFolder); var targetFolder = Path.Combine(m.OutputStorageContainer, m.OutputFolder); Console.WriteLine(@"Source full path: " + sourceFolder + "\\" + sourceFile); BlobServiceClient blobServiceClient = new BlobServiceClient(storageConnString); // 初始化源Blob客户端 BlobContainerClient sourceContainerClient = blobServiceClient.GetBlobContainerClient(sourceFolder); BlobClient sourceBlobClient = sourceContainerClient.GetBlobClient(sourceFile); // 初始化目标Blob客户端(修正:从目标容器获取) BlobContainerClient targetContainerClient = blobServiceClient.GetBlobContainerClient(targetFolder); BlobClient targetBlobClient = targetContainerClient.GetBlobClient(targetFile); if (await sourceBlobClient.ExistsAsync()) { // 获取Blob下载流(提取Content属性) var downloadInfo = await sourceBlobClient.DownloadAsync(); using var inputStream = downloadInfo.Content; // 使用内存流承接解密后的内容 using var decryptedStream = new MemoryStream(); // 初始化PGP工具并解密流 EncryptionKeys encryptionKeys = new EncryptionKeys(privateKeyValue, privateKeyPassword); PGP pgp = new PGP(encryptionKeys); await pgp.DecryptStreamAsync(inputStream, decryptedStream); // 将解密后的流重置到起始位置,再上传到目标Blob decryptedStream.Position = 0; await targetBlobClient.UploadAsync(decryptedStream, overwrite: true); Console.WriteLine("解密并上传完成: " + targetFolder + "\\" + targetFile); } else { Console.WriteLine(@"Error finding file. " + sourceFolder + "\\" + sourceFile); _log.LogError("Error find file {0}\\{1}.", sourceFolder, sourceFile); } } catch (Exception ex) { _log.LogError("Error decrypting file. EventType: {0} | File: {1} | {2} | {3} | {4}", m.EventName, m.InputFileName, ex.Message, ex.StackTrace, ex.InnerException); Console.WriteLine("Error: " + ex.Message); }
关键修正说明
- 目标Blob客户端修正:将
targetBlobClient的获取来源从sourceContainerClient改为targetContainerClient,确保上传到正确的目标容器。 - 流处理逻辑调整:用
MemoryStream承接解密后的内容,解密完成后重置流位置,再通过UploadAsync传入该流完成上传。 - 输入流提取:从
BlobDownloadInfo中获取Content作为实际输入流,确保解密工具能读取正确的源数据。
内容的提问来源于stack exchange,提问作者Caverman
相关产品推荐
相关产品推荐

