You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
}

问题修正与解决方案

核心问题点

  1. UploadAsync方法使用错误:BlobClient的UploadAsync必须接收要上传的流作为参数,无法无参获取输出流直接写入;需先通过内存流承接解密后的内容,再上传,或者使用上传时的流写入模式。
  2. 目标BlobClient指向错误:原代码中targetBlobClient从sourceContainerClient获取,会导致文件上传到源容器,需改为从targetContainerClient获取。
  3. 输入流处理错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 13:50:27