Xie Steven
Xie Steven

Reputation: 8621

How to make a download file response in .net core?

I'm using endpoints.Map("/{*name}", RequestDelegate) method to make a download file API.

In the RequestDelegate handler method, I'm using await context.Response.SendFileAsync(IFileInfo) method to return the file.

Then, I request this API in browser, but the browser did not download it, instead of showing the file content in browser directly. What's missing from my code. I want the browser to download the file.

Screenshoot

await context.Response.SendFileAsync(GetFile(val));

private IFileInfo GetFile(string file_name)
{
    string downloadPath = Configuration.GetSection("DownloadFilePath").Get<string>();
    IFileProvider provider = new PhysicalFileProvider(AppDomain.CurrentDomain.BaseDirectory);
    IFileInfo fileInfo = provider.GetFileInfo($"{downloadPath}/{file_name}");
    return fileInfo;
}

Upvotes: 1

Views: 8278

Answers (2)

Sumit Gupta
Sumit Gupta

Reputation: 2192

There are few things to consider:

  1. Browser now a days detect the file and try to handle them themselves like PDF, Txt file since they can open those file they show the content instead of downloading.
  2. To make the download it is important to ensure you send proper HTML Header, and make Content-Disposition (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition) to tell and force browser to act to your will.
  3. If you are using HTML A tag for your file you can use download attribute to tell the same thing. But I am not sure if it is fully supported.

In your code, I see you do not send header of any kind. it is good idea to set cache expiry, Disposition, Content-Type of file (since it is dynamic system will probably send default content type which can cause confusion to client side tools. ) and content-length. these are important header to send to make your code work properly.

I am not sure how to answer it properly for technical documentation purpose, but those are steps I guide to my team for when they write same code.

EDIT:

Those points are Programming language independent but on web architecture (HTTP standards).

Upvotes: 3

Xie Steven
Xie Steven

Reputation: 8621

I figured it out. I need to add the response headers for it.

var fileinfo = GetFile(val);
context.Response.Clear();
context.Response.Headers.Add("Content-Disposition", "attachment;filename=" + fileinfo.Name);
context.Response.Headers.Add("Content-Length", fileinfo.Length.ToString());
context.Response.Headers.Add("Content-Transfer-Encoding", "binary");
new FileExtensionContentTypeProvider().Mappings.TryGetValue(fileinfo.Extension, out var contenttype);
context.Response.ContentType = contenttype ?? "application/octet-stream";
await context.Response.SendFileAsync(fileinfo.FullName);

private FileInfo GetFile(string file_name)
{
    string downloadPath = Configuration.GetSection("DownloadFilePath").Get<string>();
    string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, downloadPath, file_name);
    FileInfo fileInfo = new FileInfo(path);
    return fileInfo;
}

Upvotes: 1

Related Questions