Sunday, June 8, 2014

How to stream a FileResult from one web server to another with ASP.NET MVC

MVC has a lot of great built in tooling, including the ability to stream very large file results straight from disk without having to load the whole file stream into memory.

What about the scenario where you want to stream a large file from one web server to another?

For example, I have an ASP.NET MVC application that needs to expose a download for a file hosted on another server, but I can not just redirect my users directly to the other URL. For that, we need to create a custom ActionResult type!


Here is a simple of example of what your controller might look like:

public class FileController : Controller
    public ActionResult LocalFile()
        return new FilePathResult(@"c:\files\", "application/zip");
    public ActionResult RemoteFile()
        return new WebRequestFileResult("http://otherserver/");

Here is the implementation for WebRequestFileResult:

public class WebRequestFileResult : FileResult
    private const int BufferSize = 32768; // 32 KB
    private const string DispositionHeader = "Content-Disposition";
    private const string LengthHeader = "Content-Length";
    private readonly string _url;
    public WebRequestFileResult(string url)
        : base("application/octet-stream")
        if (String.IsNullOrWhiteSpace(url))
            throw new ArgumentNullException("url", "Url is required");
        _url = url;
    protected override void WriteFile(HttpResponseBase localResponse)
        var webRequest = WebRequest.Create(_url);
        using (var remoteResponse = webRequest.GetResponse())
        using (var remoteStream = remoteResponse.GetResponseStream())
            if (remoteStream == null)
                throw new NullReferenceException(
                    "Request returned null stream: " + _url);
            var dispositionKey = remoteResponse.Headers.AllKeys.FirstOrDefault(
                k => k.Equals(
            if (!String.IsNullOrWhiteSpace(dispositionKey))
            var contentLenthString = remoteResponse.ContentLength
            localResponse.ContentType = remoteResponse.ContentType;
            localResponse.AddHeader(LengthHeader, contentLenthString);
            var buffer = new byte[BufferSize];
            var loopCount = 0;
            while (true)
                if (!localResponse.IsClientConnected)
                var read = remoteStream.Read(buffer, 0, BufferSize);
                if (read <= 0)
                localResponse.OutputStream.Write(buffer, 0, read);
                // Flush after 1 MB; note that this
                // will prevent server side caching.
                if (loopCount % 32 == 0)



  1. You should use Stream.Copy method instead of while(true) loop.

    1. When using Stream.CopyTo the response stream would not always auto flush, and the server could built up a lot of memory pressure.

    2. How can filestreamresult support resume download from url , Tom ?

  2. You completed certain reliable points there. I did a search on the subject and found nearly all persons will agree with your blog. gostream

  3. We are very excited to say that in Q2 2020 (April 1 to June 30) we saw more community involvement than ever before. Many pull requests were submitted that spanned from bug fixes for our low-level assembly to higher-level modules such as the AppKit framework. Thanks to everyone for your contributions and we hope for this level of engagement to continue.

    GOM Player Plus crack

    idm crack

    Inpixio Photo Studio Ultimate Crack

    Malwarebytes Anti Exploit Premium Crack

    IObit Driver Booster Pro Crack


Real Time Web Analytics