【问题标题】:Web api method calling a another stream content web api method?Web api 方法调用另一个流内容 web api 方法?
【发布时间】:2013-04-07 02:38:54
【问题描述】:

这是我的情况,我有两个 web api 服务。第一个有一个处理一些数据的方法,当部分数据准备好时,它会将其推送到流中。

public HttpResponseMessage Get( )
        {
            var response = Request.CreateResponse( );
            response.Content = new PushStreamContent( WriteToStream );
            return response;
        }

        public async void WriteToStream( Stream outputStream, HttpContent content, TransportContext context )
        {
            .......
        }

第二个 web api 在控制器中有一个调用第一个 web api 的方法。它必须从流中读取部分并对其进行处理并将 i 放入它自己的流中:

public HttpResponseMessage Get( )
        {
            Stream stream = null;

            using( HttpClient httpClient = new HttpClient( ) )
            {
                httpClient.Timeout = TimeSpan.FromMilliseconds( Timeout.Infinite );
                HttpRequestMessage request = new HttpRequestMessage( HttpMethod.Get, "http://localhost/fistWebApi/" );

                var response = httpClient.SendAsync( request, HttpCompletionOption.ResponseContentRead );

                var content = response.Result.Content.ReadAsStreamAsync( );

                stream = content.Result;
            }

            var msg = Request.CreateResponse( );

            msg.Content = new PushStreamContent( WriteToStream );

            return msg;
        }
public async void WriteToStream( Stream outputStream, HttpContent content, TransportContext context )
            {
                .......
            }

问题是我不知道如何同步调用SendAsyncReadAsStreamAsync。现在它不会等待并且stream 在尝试使用它时未正确初始化。我希望第二种方法的代码等到第一种方法将部分数据放入流中。我尝试使用ContinueWith,但后来我无法做到。我知道这是一个有点模糊的解释,如果有任何问题我会尝试更深入地解释。

【问题讨论】:

    标签: c# asp.net-web-api


    【解决方案1】:

    试试这个...

     public HttpResponseMessage Get()
            {
    
                using (HttpClient httpClient = new HttpClient())
                {
                    httpClient.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
                    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://www.google.ca");
    
                    return httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
                        .ContinueWith((t) =>
                            {
                                return new HttpResponseMessage()
                                    {
                                        Content = t.Result.Content
                                    };
                            }).Result;
    
                }
    
            }
    

    上面的代码对我有用。这样做的缺点是因为您使用了HttpCompletionOption.ResponseContentRead,所以来自远程服务的整个有效负载将在返回给您的客户端之前进行缓冲。

    如果您改为使用HttpCompletionOption.ResponseHeadersReadt.Result.Content 将改为返回网络流。这样,当您的客户端拉取响应流时,它将直接从远程资源流式传输。我假设这就是您当前正在尝试对返回的 PushStreamContent 执行的操作。

    【讨论】:

    • 你不应该通过将状态码传递给构造函数来转发它吗?即:新的HttpResponseMessage(t.result.StatusCode)
    • @eventualEntropy 是的。并复制标题。并通过使方法异步来摆脱那些讨厌的 .Result 调用。这段代码有很多错误。
    • 很好的答案,我在两个 API 之间构建了一种“代理”,我一直在努力寻找一种无需在 RAM 中缓冲整个文件即可流式传输大文件的方法,这就是解决方案!我发现了一个重要提示:如果您在 Web Api 自托管项目中使用它,请确保您还延长了 HttpSelfHostConfiguration 对象的超时时间,否则持续时间超过 60 秒的请求将失败。
    • 在下载大内容时,会产生网络错误。
    猜你喜欢
    • 2014-12-11
    • 2015-08-24
    • 1970-01-01
    • 2016-12-01
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 2013-01-14
    相关资源
    最近更新 更多