Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net Core Content-Disposition attachment/inline

I am returning a file from a WebAPI controller. The Content-Disposition header value is automatically set to "attachment". For example:

Disposition: attachment; filename="30956.pdf"; filename*=UTF-8''30956.pdf

When it is set to attachment the browser will ask to save file instead of opening it. I would like it to open it.

How can I set it to "inline" instead of "attachment"?

I am sending the file using this method:

public IActionResult GetDocument(int id)
{
    var filename = $"folder/{id}.pdf";
    var fileContentResult = new FileContentResult(File.ReadAllBytes(filename), "application/pdf")
    {
        FileDownloadName = $"{id}.pdf"
    };
    // I need to delete file after me
    System.IO.File.Delete(filename);

    return fileContentResult;
}
like image 770
Tedd Hansen Avatar asked Aug 11 '16 13:08

Tedd Hansen


People also ask

What is the difference between inline and attachment in content-disposition?

Content-Disposition takes one of two values, `inline' and `attachment'. 'Inline' indicates that the entity should be immediately displayed to the user, whereas `attachment' means that the user should take additional action to view the entity.

What is ContentDisposition in C#?

ContentDisposition() Initializes a new instance of the ContentDisposition class with a DispositionType of Attachment. ContentDisposition(String) Initializes a new instance of the ContentDisposition class with the specified disposition information.

What is content-disposition attachment filename?

Content-Disposition: attachment; filename=FILENAME. The filename parameter can be used to suggest a name for the file into which the resource is downloaded by the browser.


4 Answers

The best way I have found is to add the content-disposition headers manually.

private IActionResult GetFile(int id)
{
       var file = $"folder/{id}.pdf";

       // Response...
       System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
       {
              FileName = file,
              Inline = displayInline  // false = prompt the user for downloading;  true = browser to try to show the file inline
       };
       Response.Headers.Add("Content-Disposition", cd.ToString());
       Response.Headers.Add("X-Content-Type-Options", "nosniff");

       return File(System.IO.File.ReadAllBytes(file), "application/pdf");
}
like image 106
Ashley Lee Avatar answered Oct 17 '22 16:10

Ashley Lee


With version 2.0.0 of AspNetCore and AspNetCore.Mvc, I found none of the previous answers to be acceptable. For me, simply ommitting the filename argument to File was enough to trigger an inline content disposition.

return File(fileStream, contentType, fileName); // attachment
return File(fileStream, contentType);           // inline

Update

In .NET 6, set the Content-Disposition header to inline or attachment by adding it to the response header:

// inline
Response.Headers.Add("Content-Disposition", "inline");
return File(fileStream, contentType);

// attachment
Response.Headers.Add("Content-Disposition", "attachment;filename=some.txt");
return File(fileStream, contentType);
like image 38
Jonathan Wilson Avatar answered Oct 17 '22 16:10

Jonathan Wilson


Given you don't want to read the file in memory at once in a byte array (using the various File(byte[]...) overloads or using FileContentResult), you can either use the File(Stream, string, string) overload, where the last parameter indicates the name under which the file will be presented for download:

return File(stream, "content/type", "FileDownloadName.ext");

Or you can leverage an existing response type that supports streaming, such as a FileStreamResult, and set the content-disposition yourself. The canonical way to do this, as demonstrated in the FileResultExecutorBase, is to simply set the header yourself on the response, in your action method:

// Set up the content-disposition header with proper encoding of the filename
var contentDisposition = new ContentDispositionHeaderValue("attachment");
contentDisposition.SetHttpFileName("FileDownloadName.ext");
Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();

// Return the actual filestream
return new FileStreamResult(@"path\to\file", "content/type");
like image 14
CodeCaster Avatar answered Oct 17 '22 14:10

CodeCaster


You can override the default FileContentResult class so you can use it in your code with minimal changes:

public class InlineFileContentResult : FileContentResult
{
    public InlineFileContentResult(byte[] fileContents, string contentType)
        : base(fileContents, contentType)
    {
    }

    public override Task ExecuteResultAsync(ActionContext context)
    {
        var contentDispositionHeader = new ContentDispositionHeaderValue("inline");
        contentDispositionHeader.SetHttpFileName(FileDownloadName);
        context.HttpContext.Response.Headers.Add(HeaderNames.ContentDisposition, contentDispositionHeader.ToString());
        FileDownloadName = null;
        return base.ExecuteResultAsync(context);
    }
}

The same can be done for the FileStreamResult:

public class InlineFileStreamResult : FileStreamResult
{
    public InlineFileStreamResult(Stream fileStream, string contentType)
        : base(fileStream, contentType)
    {
    }

    public override Task ExecuteResultAsync(ActionContext context)
    {
        var contentDispositionHeader = new ContentDispositionHeaderValue("inline");
        contentDispositionHeader.SetHttpFileName(FileDownloadName);
        context.HttpContext.Response.Headers.Add(HeaderNames.ContentDisposition, contentDispositionHeader.ToString());
        FileDownloadName = null;
        return base.ExecuteResultAsync(context);
    }
}

Instead of returning a FileContentResult or FileStreamResult, just return InlineFileContentResult or InlineFileStreamResult. F.e.:

public IActionResult GetDocument(int id)
{
    var filename = $"folder/{id}.pdf";
    return new InlineFileContentResult(File.ReadAllBytes(filename), "application/pdf")
    {
        FileDownloadName = $"{id}.pdf"
    };
}

Warning

As pointed out by makman99, do not use the ContentDisposition class for generating the header value as it will insert new-lines in the header-value for longer filenames.

like image 13
huysentruitw Avatar answered Oct 17 '22 14:10

huysentruitw