How to return a FileResult using an Amazon S3 ResponseStream?

Viewed 1241

Using the AWSSDK.S3 nuget package, I'm trying to return a file that has been retrieved from an S3 bucket. My starting point is based on the example given in this SO answer.

Example controller code:

public FileResult GetFile(Guid id)
{
    // no using block as it will be disposed of by the File method
    var amazonResponse = _foo.GetAmazonResponseWrapper(_user, id);
    // set Response content-length header
    // set Response content-type header

    var bufferSize = 1024;
    var buffer = new byte[bufferSize];
    int bytesRead;

    while ((bytesRead = amazonResponse.ResponseStream.Read(buffer, 0, buffer.Length)) > 0 && Response.IsClientConnected)
    {
        Response.OutputStream.Write(buffer, 0, bytesRead);
        Response.OutputStream.Flush();
        buffer = new byte[bufferSize];
    }        

    // this will not work (can't read from this stream)
    return File(Response.OutputStream, "text/plain", "bar.txt");
}

If I write to a MemoryStream I create and use in the while loop, I will get a file, but there won't be any content.

The only way I've found to get content in the file is to call .ToArray() on the stream like so:

return File(memStream.ToArray(), "text/plain", "foo.txt");

Is there a way to actually stream a file to the browser without loading it into the memory of the web server?

1 Answers

Just pass the stream forward

public FileResult GetFile(Guid id) {
    // no using block as it will be disposed of by the File method
    var amazonResponse = _foo.GetAmazonResponseWrapper(_user, id);
    return File(amazonResponse.ResponseStream, "text/plain", "bar.txt");
}

You have already shown that you can read from the response stream. Then just pass the response stream on and the File result will read it and return the response.

Related