I have a controller action which should return a FileStreamResult
.
This action is triggered by a button click on a "Downloads" page.
public class SoftwareUpdatesDownloadController : BaseController
{
public virtual async Task<ActionResult> Entity(EntityModel entity, int containerSize = 0)
{
//some action preparation & validation code, omitted for clarity
Stream stream = await GetFileStream(model.Updates[GetUpdateNumberFromQueryString()].UpdateLink).ConfigureAwait(false);
return File(stream, "application/octet-stream",GetFileNameFromLink(model.Updates[GetUpdateNumberFromQueryString()].UpdateLink));
//return new FileStreamWithLengthResult(stream, "application/octet-stream", GetFileNameFromLink(model.Updates[GetUpdateNumberFromQueryString()].UpdateLink));<--same behaviour
}
}
When this code is executed, an error is thrown:
And the browser downloads a text file which contains an html of the current page (with the above error message text in the middle).
I tried using a custom action result, which results in the same behaviour, the only difference being that I see more exactly where the error is thrown:
public class FileStreamWithLengthResult : ActionResult
{
private Stream stream;
private string mimeType;
private string fileName;
private long contentLength;
public FileStreamWithLengthResult(Stream stream,string mimeType,string fileName)
{
this.stream = stream;
this.mimeType = mimeType;
this.fileName = fileName;
this.contentLength = stream.Length;
}
public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.Response;
response.BufferOutput = false;
response.Headers.Add("Content-Type", mimeType);
response.Headers.Add("Content-Length", contentLength.ToString());
response.Headers.Add("Content-Disposition", "attachment; filename=" + fileName);
using (stream)
{
stream.CopyTo(response.OutputStream); //the error is thrown here (output stream is not available when a custom TextWriter is used
}
response.End();
}
}
As far as I understand DXA (which is little), the regions of the page are rendered using the @Html.DxaRegion()
and @Html.DxaEntities()
helpers - and these are the custom TextWriters - and when these are in use, it is not possible to access the output stream of the HTTP response.
Therefore, the question is - how should the files for download be served from webapps which use DXA?
Also, just to be sure that there is no problem with the stream I am returning, I have used the very same code in a blank MVC app, and there it works just fine.