Asp.net core mvc 如何在.net core中转发来自远程服务器的响应?

Asp.net core mvc 如何在.net core中转发来自远程服务器的响应?,asp.net-core-mvc,Asp.net Core Mvc,我想我掉进了一个兔子洞,我怀疑有一个比我正在尝试的更简单的解决方案。基本上,在我的.net核心MVC应用程序中,我想从外部API提取一个流式视频文件 这意味着,对于对我的操作的任何请求,我希望通过连接调用一个外部API函数。我需要向请求中添加一个头,但要传递所有其他已请求的头,然后在收到API的回复后,我会将整个响应转发给使用者。它基本上就像一个没有状态码的重定向,并向重定向的源添加一个头 我的做法如下。在我的控制器中,我调用ForwardedResponseResult: var client

我想我掉进了一个兔子洞,我怀疑有一个比我正在尝试的更简单的解决方案。基本上,在我的.net核心MVC应用程序中,我想从外部API提取一个流式视频文件

这意味着,对于对我的操作的任何请求,我希望通过连接调用一个外部API函数。我需要向请求中添加一个头,但要传递所有其他已请求的头,然后在收到API的回复后,我会将整个响应转发给使用者。它基本上就像一个没有状态码的重定向,并向重定向的源添加一个头

我的做法如下。在我的控制器中,我调用ForwardedResponseResult:

var client = await this.FileAssetsApiContext.GetHttpClient();
//Copy the Headers
foreach (var header in Request.Headers)
{
    header.Value.ToList().ForEach(p => {
        if (client.DefaultRequestHeaders.Contains(header.Key))
        {
            client.DefaultRequestHeaders.Remove(header.Key);
            client.DefaultRequestHeaders.Add(header.Key, p);
         }
         else
         {
             client.DefaultRequestHeaders.Add(header.Key, p);
         }});
    }

    var fullPath = Url.Combine(VideosRootPath, path);
    var response = await client.GetAsync(url);
    return new ForwardedResponseResult(response);     
然后我有一个转发类:

  public class ForwardedResponseResult : ActionResult
{
    public override void ExecuteResult(ActionContext context)
    {
        throw new NotImplementedException();
    }
    public ForwardedResponseResult(HttpResponseMessage httpResponseMessage)
    {
        this.HttpResponseMessage = httpResponseMessage;
    }

    public override async Task ExecuteResultAsync(ActionContext context)
    {
        var responseToCopy = this.HttpResponseMessage;
        var responseToCopyHeaders = responseToCopy.Headers.ToArray();
        var responseToCopyContentHeaders = responseToCopy.Content.Headers.ToArray();
        var streamToCopy = await responseToCopy.Content.ReadAsStreamAsync();
        var responseToReturnTo = context.HttpContext.Response;
        var streamToCopyTo = responseToReturnTo.Body;

        var headers = responseToCopy.Headers.ToArray();
        var contentHeaders = responseToCopy.Content.Headers.ToArray();
        var headersTo = responseToReturnTo.Headers.ToArray();

        foreach (var header in responseToCopy.Headers)
        {
                header.Value.ToList().ForEach(p => responseToReturnTo.Headers.Add(header.Key, p));
        }
        responseToReturnTo.StatusCode = (int) responseToCopy.StatusCode;

        foreach (var header in responseToCopy.Content.Headers)
        {
            header.Value.ToList().ForEach(p => responseToReturnTo.Headers.Add(header.Key, p));
        }

        //Copy to the output buffer
        var remainingBytes = streamToCopy.Length;

        while (remainingBytes > 0)
        {
            //var bufferSize = 1024;
            var bufferSize = 8096;
            var buffLen = remainingBytes > bufferSize ? bufferSize : remainingBytes;
            var buffer = new byte[buffLen];
            streamToCopy.Read(buffer, 0, (int)buffLen);
            streamToCopyTo.Write(buffer, 0, (int)buffLen);
            remainingBytes -= buffLen;
        }
        //streamToCopy.CopyTo(streamToCopyTo);
        //await streamToCopyTo.FlushAsync();

    }
    public HttpResponseMessage HttpResponseMessage { get; }

}
这似乎有点过分,范围请求的性能非常糟糕。我错过了什么明显的东西吗?有没有更简单的方法

我想从外部API提取流式视频文件

如果下载量很大,请确保使用

此外,您还可以利用。像这样的方法应该会奏效:

var client = await this.FileAssetsApiContext.GetHttpClient();
... // Copy Request.Headers to client.DefaultRequestHeaders.

var fullPath = Url.Combine(VideosRootPath, path);
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
var stream = await client.Content.ReadAsStreamAsync();

... // Copy response.Headers / response.Content.Headers to Response.Headers
return File(stream, "application/octet-stream");

我不知道有什么干净的方法可以复制请求/响应头,但它似乎是一些实用方法的好地方。

谢谢Stephen。这种改变效果更好。我很惊讶没有直接的方法来做这件事,但至少我有它的工作