如何在ASP.NET Web API中设置下载文件名


140

在我的ApiController类中,我有以下方法可以下载服务器创建的文件。

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);
    }
}

除了默认的下载文件名是其ID外,其他所有东西都可以正常运行,因此用户可能每次必须在保存为对话框时键入自己的文件名。有什么方法可以在上面的代码中设置默认文件名?


1
您可以共享用于调用此方法的代码吗?
Yasser Shaikh 2012年

@Yasser-这是一个Web API控制器方法-可能是通过进入IIS的HTTP请求并对其进行解析并找到路由和Web API调用该方法而调用的(当然,它也被测试调用)。
Dave Rael 2014年

GetMyForm()内部发生了什么?将文件转换成字节流?
MSIslam

@MSIslam之类的。该函数从用户的表单获取信息并创建文件,然后再转换为结果流。
泰成新

Answers:


288

您需要在上设置Content-Disposition标题HttpResponseMessage

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

21
对于任何对“附件”处置类型感到好奇的人,处置类型的完整列表在iana.org/assignments/cont-disp/cont-disp.xhtml
sfuqua 2014年

1
您还有另一个在这里下载文件的答案是否使用System.Net.Mime.ContentDisposition还是重要ContentDispositionHeaderValue?一个比另一个更流行,更优先吗?
发光

@Luminous一个答案是ActionResult,一个是为HttpResponseMessage
韦斯顿

@weston您的回复未回答我的问题。
发光的

4
@Luminous:“这有关系吗?”和“是否比另一个更流行,更可取?” 不,不。一种用于MVC ActionResult,一种用于WebApi HttpResponseMessage
Weston,2015年

27

编辑:如评论中所述,我的答案未考虑需要像一样转义的字符;。如果您的文件名可以包含分号,则应使用Darin接受的答案。

添加Response.AddHeader以设置文件名

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

只需将FILE_NAME更改为文件名即可。


2
事实证明,这对我解决与提问者类似的问题很有帮助。以我为例,我还发现将“附件”更改为“内联”很有用,以便IE8为我提供始终打开有问题的文件类型的选项。
斯科特,

2
不涵盖转义。如果文件名包含;或具有特殊含义的其他内容怎么办?
2015年

萨姆,三年前我写这个答案的时候,我没有意识到我的答案需要处理转义。感谢您向我指出这一点,我对答案进行了修改,解释了我的答案并没有说明转义。但是我的回答保持不变,因为它似乎对人们有所帮助。
KingPancake 2015年

8

如果要确保文件名正确编码,又避免使用WebApi HttpResponseMessage,则可以使用以下命令:

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

您可以使用ContentDisposition或ContentDispositionHeaderValue。在任意一个实例上调用ToString将为您进行文件名编码。


6

我认为这可能对您有帮助。

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

4
不涵盖转义。如果文件名包含;或具有特殊含义的其他内容怎么办?
2015年

3

您需要将content-disposition标头添加到响应中:

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

3
不涵盖转义。如果文件名包含;或具有特殊含义的其他内容怎么办?
2015年

3

如果您使用的是ASP.NET Core MVC,则上面的答案会稍作更改...

在我的操作方法(返回async Task<JsonResult>)中,添加行(在return语句之前的任意位置):

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

不涵盖转义。如果文件名包含;,该怎么办?或其他具有特殊含义的东西?
KoalaBear

2

应该这样做:

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

2
不涵盖转义。如果文件名包含;或具有特殊含义的其他内容怎么办?
2015年

0

注意:最后一行是必填项。

如果未指定Access-Control-Expose-Headers,则不会在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");

0

考虑到先前的答案,有必要小心使用全球化字符。

假设文件的名称为:“ Esdrújulaprendañame-güena.jpg

原始结果下载:“EsdrÃÃjulaprendañame-güena.jpg” [丑陋]

HtmlEncode结果下载:“ Esdr&_250; jula prenda&_241; ame-g&_252; ena.jpg” [丑陋]

UrlEncode结果下载:“ Esdrújula+ prenda +ñame+-++güena.jpg ” [确定]

然后,几乎总是需要在文件名上使用UrlEncode。此外,如果将content-disposition标头设置为直接字符串,则需要确保用引号引起来,以避免浏览器兼容性问题。

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

或在课堂帮助下:

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

System.Net.Mime。ContentDisposition类负责引号。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.