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

Azure函数执行后出现未处理主机错误的问题排查

问题:Azure函数返回Blob后抛出未处理主机错误

问题背景

我编写了一个基于HTTP触发的Azure函数,用于下载Blob。本地调试时,代码完整执行完毕并返回结果后,会抛出模糊错误,导致返回无法送达测试应用。

原函数代码

public class GetBlob
{
    private readonly IUpgradeDataRepositoryFactory _upgradeDataRepository;
    private readonly IAuthorizationHelper _authorizationHelper;

    public GetBlob(IUpgradeDataRepositoryFactory upgradeDataRepository, IAuthorizationHelper authorizationHelper){
        _upgradeDataRepository = upgradeDataRepository;
        _authorizationHelper = authorizationHelper;
    }

    [FunctionName("GetBlob")]
    public HttpResponseMessage Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "GetBlob/{id}")] HttpRequest req,
        string id, ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
        var clientIp = (req.Headers["X-Forwarded-For"].FirstOrDefault() ?? "").Split(new char[] { ':' }).FirstOrDefault();

        try{
            _authorizationHelper.AssertRequestIsAuthorized(req);

            var blobInfo = _upgradeDataRepository.UpdateDataItemRepository.Query(q => q.BlobName == id).FirstOrDefault();
            if(blobInfo != null){
                using (var blobStream = GetBlobStream(id))
                {
                    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
                    result.Content = new StreamContent(blobStream);
                    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                    result.Content.Headers.ContentDisposition.FileName = blobInfo.BlobFriendlyName;
                    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                    log.LogInformation(string.Format("Returning Update Blob: {0} to ip: {1}", id, clientIp));
                    return result;
                }
            }
            else
            {
                log.LogInformation(string.Format("Could not find update item record for blob id: {0} Ip: {1}", id, clientIp));
                return new HttpResponseMessage(HttpStatusCode.NotFound);
            }
        }
        catch (AuthorizationException){
            log.LogInformation("Authorization failed");
            var message = new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.Unauthorized
            };
            throw new HttpResponseException(message);
        }
        catch (Exception ex){
            log.LogError(string.Format("Error getting update blob: {0} for IP: {1}", id, clientIp));
            log.LogError(ex.ToString());
            throw new HttpResponseException(HttpStatusCode.BadRequest);
        }
        finally{
            log.LogInformation(string.Format("Exiting Get Update Blob: {0} for ip: {1}", id, clientIp));
        }
    }

    private static CloudStorageAccount GetStorageAccount()
    {
        var connParameter= "StorageAccountConnectionString";
        var connectionString = System.Environment.GetEnvironmentVariable($"{connParameter}");
        return CloudStorageAccount.Parse(connectionString);       
    }

    private static string GetContainerName(){
        var containerParameter= "UpdateBlobContainerName";
        var containerName = System.Environment.GetEnvironmentVariable($"{containerParameter}");
        return containerName;
    }


    private static Stream GetBlobStream(string id)
    {
        CloudStorageAccount account = GetStorageAccount();
        CloudBlobClient blobClient = account.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference(GetContainerName());
        var blob = container.GetBlobReference(id);

        return blob.OpenReadAsync().Result;
    }
}

补充说明

  • 使用HttpResponseMessage是为了替代旧API,适配原有代码
  • AuthenticationHelper和UpgradeDataRepository已在其他正常函数中验证,问题应与Blob存储操作相关

终端输出日志

[2024-03-27T19:04:34.288Z] Executing 'GetBlob' (Reason='This function was programmatically called via the host APIs.', Id=5b3af3ef-c61e-4ad7-a582-4982ba9d6b3e)
[2024-03-27T19:04:34.300Z] C# HTTP trigger function processed a request.
[2024-03-27T19:04:41.904Z] Returning Update Blob: 729ee33f-e283-420a-b898-648718139e3a to ip: 
[2024-03-27T19:04:41.906Z] Exiting Get Update Blob: 729ee33f-e283-420a-b898-648718139e3a for ip:
[2024-03-27T19:04:41.907Z] Executed 'GetBlob' (Succeeded, Id=5b3af3ef-c61e-4ad7-a582-4982ba9d6b3e, Duration=7650ms)
[2024-03-27T19:04:41.915Z] An unhandled host error has occurred.
[2024-03-27T19:04:41.916Z] Microsoft.WindowsAzure.Storage: Object reference not set to an instance of an object.

可见函数执行成功的日志出现后,随即抛出错误。猜测可能是版本不兼容,附上项目文件:

项目文件内容

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.14">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.14" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.14">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.2.0" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

更新尝试:切换到Azure.Storage.Blobs

将Microsoft.Windows.Azure替换为Azure.Storage.Blobs,修改后的Blob操作代码如下:

private static BlobServiceClient GetStorageAccount()
{
    var connParameter= "StorageAccountConnectionString";
    var connectionString = System.Environment.GetEnvironmentVariable($"{connParameter}");
    return new BlobServiceClient(connectionString);           
}

private static Stream GetBlobStream(string id)
{
    BlobServiceClient account = GetStorageAccount();
    BlobContainerClient container = account.GetBlobContainerClient(GetContainerName());
    var blob = container.GetBlobClient(id);

    return blob.OpenReadAsync().Result;
}

更新后的终端错误日志

[2024-03-28T12:09:20.144Z] Executed 'GetBlob' (Succeeded, Id=08567df1-e23f-4973-a9e5-a9750f0ff9ee, Duration=4304ms)
[2024-03-28T12:09:20.322Z] An unhandled host error has occurred.
[2024-03-28T12:09:20.323Z] System.Private.CoreLib: Value cannot be null. (Parameter 'buffer').

内容的提问来源于stack exchange,提问作者Kenbo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 23:15:54