尝试将 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的主要内容,如果未能解决你的问题,请参考以下文章
尝试从 UIViewController 将属性分配给 UIScrollView 类
尝试将数据从子活动返回到 MainActivity 时获取 NullPointerException