Tae-Sung Shin
Tae-Sung Shin

Reputation: 20620

How to set downloading file name in ASP.NET Web API

In my ApiController class, I have following method to download a file created by server.

public HttpResponseMessage Get(int id)
{
    try
    {
        string dir = HttpContext.Current.Server.MapPath("~"); //location of the template file
        Stream file = new MemoryStream();
        Stream result = _service.GetMyForm(id, dir, file);
        if (result == null)
        {
            return Request.CreateResponse(HttpStatusCode.NotFound);
        }
        result.Position = 0;
        HttpResponseMessage response = new HttpResponseMessage();
        response.StatusCode = HttpStatusCode.OK;
        response.Content = new StreamContent(result);
        return response;
    }
    catch (IOException)
    {
        return Request.CreateResponse(HttpStatusCode.InternalServerError);
    }
}

Everything is working perfect except that default downloading file name is its id so user might have to type his/her own file name at save as dialog each time. Is there any way to set a default file name in the code above?

Upvotes: 149

Views: 118148

Answers (9)

Asereware
Asereware

Reputation: 1049

Considering the previous answers, it is necessary to be careful with globalized characters.

Suppose the name of the file is: "Esdrújula prenda ñame - güena.jpg"

Raw result to download: "Esdrújula prenda ñame - güena.jpg" [Ugly]

HtmlEncode result to download: "Esdr&_250;jula prenda &_241;ame - g&_252;ena.jpg" [Ugly]

UrlEncode result to download: "Esdrújula+prenda+ñame+-+güena.jpg" [OK]

Then, you need almost always to use the UrlEncode over the file name. Moreover, if you set the content-disposition header as direct string, then you need to ensure surround with quotes to avoid browser compatibility issues.

Response.AddHeader("Content-Disposition", $"attachment; filename=\"{HttpUtility.UrlEncode(YourFilename)}\"");

or with class aid:

var cd = new ContentDisposition("attachment") { FileName = HttpUtility.UrlEncode(resultFileName) };
Response.AddHeader("Content-Disposition", cd.ToString());

The System.Net.Mime.ContentDisposition class takes care of quotes.

Upvotes: 1

Chandan Y S
Chandan Y S

Reputation: 1078

Note: The last line is mandatory.

If we didn't specify Access-Control-Expose-Headers, we will not get File Name in UI.

FileInfo file = new FileInfo(FILEPATH);

HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
    FileName = file.Name
};
response.Content.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

Upvotes: 0

Peter
Peter

Reputation: 1121

If you are using ASP.NET Core MVC, the answers above are ever so slightly altered...

In my action method (which returns async Task<JsonResult>) I add the line (anywhere before the return statement):

Response.Headers.Add("Content-Disposition", $"attachment; filename={myFileName}");

Upvotes: 3

tucaz
tucaz

Reputation: 6684

This should do:

Response.AddHeader("Content-Disposition", "attachment;filename="+ YourFilename)

Upvotes: 2

sorenhk
sorenhk

Reputation: 1607

If you want to ensure that the file name is properly encoded but also avoid the WebApi HttpResponseMessage you can use the following:

Response.AddHeader("Content-Disposition", new System.Net.Mime.ContentDisposition("attachment") { FileName = "foo.txt" }.ToString());

You may use either ContentDisposition or ContentDispositionHeaderValue. Calling ToString on an instance of either will do the encoding of file names for you.

Upvotes: 10

AndyC
AndyC

Reputation: 1335

EDIT: As mentioned in a comment, My answer doesn't account for characters that need to be escaped like a ;. You should use the accepted answer Darin made if your file name could contain a semi-colon.

Add a Response.AddHeader to set the file name

Response.AddHeader("Content-Disposition", "attachment; filename=*FILE_NAME*");

Just change FILE_NAME to the name of the file.

Upvotes: 28

Darin Dimitrov
Darin Dimitrov

Reputation: 1039100

You need to set the Content-Disposition header on the HttpResponseMessage:

HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
response.Content = new StreamContent(result);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
    FileName = "foo.txt"
};

Upvotes: 308

Carl Raymond
Carl Raymond

Reputation: 4479

You need to add the content-disposition header to the response:

 response.StatusCode = HttpStatusCode.OK;
 response.Content = new StreamContent(result);
 response.AppendHeader("content-disposition", "attachment; filename=" + fileName);
 return response;

Upvotes: 3

Jarek
Jarek

Reputation: 3379

I think that this might be helpful to you.

Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName)

Upvotes: 6

Related Questions