尝试将 HttpClient.GetStreamAsync 直接用于 adls FileClient.UploadAsync

Posted

技术标签:

【中文标题】尝试将 HttpClient.GetStreamAsync 直接用于 adls FileClient.UploadAsync【英文标题】:Trying to use HttpClient.GetStreamAsync straight to the adls FileClient.UploadAsync 【发布时间】:2021-09-11 15:04:42 【问题描述】:

我有一个 Azure 函数,它将通过 HttpClient 调用外部 API。外部 API 返回 JSON 响应。我想将响应直接保存到 ADLS 文件中。

我的简单代码是:

public async Task UploadFileBulk(Stream contentToUpload)

   await this._theClient.FileClient.UploadAsync(contentToUpload);            

this._theClient 是围绕各种 Azure Data Lake 类(如 DataLakeServiceClient、DataLakeFileSystemClient、DataLakeDirectoryClient、DataLakeFileClient)的简单包装类。

我很高兴这个包装器调用按我的预期工作,我启动一个,设置服务、文件系统、目录,然后创建一个文件名。我已经使用这个包装类来创建目录等,所以它可以按我的预期工作。

我是这样调用上面的方法的:

await dlw.UploadFileBulk(await this._httpClient.GetStreamAsync("<endpoint>"));  

我看到在 Lake 目录中创建了我想要的文件,但是如果我使用 Sorage Explorer 下载该文件,然后尝试用 VS Code 打开它,它不是可识别的格式(我可以“强制" 代码打开它,但它看起来像二进制格式)。

如果我用 fiddler 嗅探流量,我可以看到来自外部 API 的内容是 JSON,content-type 是 application/json,body 在 fiddler 中显示为 JSON。

如果我查看对 ADLS 端点的调用,我可以看到一个 PUT 调用,然后是两个 PATCH 调用。

第一个 PATCH 调用看起来像是发送内容的调用,它的内容标头为 application/octet-stream,请求正文是“二进制内容”。

我正在使用 HttpClient.GetStreamAsync,因为我不希望我的函数必须将整个 API 有效负载加载到内存中(一些外部 API 端点返回超过 100mb 的非常大的文件)。我想我可以“将来自外部 API 的响应直接流式传输到 ADLS”。

有没有办法改变 ADLS FileClient.UploadAsync(Stream stream) 方法的工作方式,以便我可以告诉它以 JSON 文件的形式上传文件,内容类型为 application/json?

编辑: 事实证明,外部 API 正在发回压缩内容,所以一旦我将以下额外的 AutomaticDecompression 代码添加到我的函数启动中,我就会按预期将文件上传到 ADLS。

        public override void Configure(IFunctionsHostBuilder builder)
    
        builder.Services.AddHttpClient("default", client =>
        
            client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");

        ).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
        
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        );
    

@Gaurav Mantri 给了我一些关于“从输出到输入的流”模式是否真的正确的指示,我会进一步研究。

【问题讨论】:

请看看这是否有帮助:***.com/questions/65615193/…. 谢谢,我已经更新了帖子,给出了我为什么要获取二进制数据的答案,但是您的评论为我提供了一个良好的开端,让我了解如何编写“从结果到输入的流”模式"。 【参考方案1】:

关于问题,请参考以下代码

var uploadOptions = new DataLakeFileUploadOptions();
uploadOptions.HttpHeaders = new PathHttpHeaders();
uploadOptions.HttpHeaders.ContentType ="application/json";
await fileClient.UploadAsync(stream, uploadOptions);

【讨论】:

谢谢@jim,我已经更新了帖子,回答了我为什么要获取二进制数据

以上是关于尝试将 HttpClient.GetStreamAsync 直接用于 adls FileClient.UploadAsync的主要内容,如果未能解决你的问题,请参考以下文章

尝试将多个 Uitextfields 添加为整数 [重复]

尝试从 UIViewController 将属性分配给 UIScrollView 类

尝试将指针与结构一起使用时出错

尝试将数据从子活动返回到 MainActivity 时获取 NullPointerException

尝试将 xml 导入到 android 时出现 OutOfMemoryException

尝试将数字写入二进制文件时引发异常