如何避免与MVC3 FileContentResult重复的内容处置头? [英] How to avoid duplicate content-disposition headers with MVC3 FileContentResult?

查看:151
本文介绍了如何避免与MVC3 FileContentResult重复的内容处置头?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们必须存储在SQL数据库的一些文件。在一个ASP.NET MVC3的形式,我们会显示2链接:

查看这个文件|下载此文件

这些链接到这些相应的操作方法。下载将按预期 - 点击链接强制在浏览器中保存对话框。但是,显示是造成重复的内容处置头被发送到浏览器,导致在Chrome的错误,并在Firefox中的空白页。

  [ActionName(显示文件)]
公共虚拟的ActionResult DisplayFile(GUID FILEID,字符串文件名)
{
    var文件= _repos.GetFileInfo(FILEID);
    如果(文件!= NULL)
    {
        Response.AddHeader(内容处置,
            的String.Format(内联;文件名= {0},file.Name));
        返回文件(file.Content,file.MimeType,file.Name);
    }
}[ActionName(下载文件)]
公共虚拟的ActionResult DownloadFile(GUID FILEID,字符串文件名)
{
    var文件= _repos.GetFileInfo(FILEID);
    如果(文件!= NULL)
    {
        返回文件(file.Content,file.MimeType,file.Name);
    }
}

下面是发送到浏览器的显示动作的2头

 内容处置:内联;文件名=名称的-MY-file.pdf
内容处置:附件;文件名=名称的-MY-file.pdf

我试图改变我的自定义内容处置头在双引号包文件名,但它仍然派出2头到浏览器。我也尝试添加自定义的人之前删除内容处置头,但它似乎返回FileContentResult之后被添加附件头。

这code用来工作。我昨天刚跑了测试,发现它不再是在Chrome或Firefox的工作。这可能是由于在浏览器的更新。 IE8和Safari浏览器仍然可以正确打开文件。

更新

再次感谢达林,你是正确的。事实上,我们使用,因为你的回答的另一个问题。

有关如何这是最终解决了我们这边出了一点信息,我们为显示文件链接的自定义路线:

  context.MapRoute(NULL,
    路径/要/显示-文件附件/ {FILEID} / {文件名},
    新
    {
        面积=AREANAME
        控制器=ControllerName
        行动=DisplayFile
    }
);

在页面上超链接传递的文件名通过路由参数的操作方法,所以它已经是URL的一部分。因此,我们没有必要为了使文件名匹配系统,当用户决定下载(点击保存图标在浏览器PDF浏览器)添加自定义内容处置头。所以,我们只是用这样的:

  [ActionName(显示文件)]
公共虚拟的ActionResult DisplayFile(GUID FILEID,字符串文件名)
{
    var文件= _repos.GetFileInfo(FILEID);
    如果(文件!= NULL)
    {
        //没有自定义内容处置头,并没有第三个文件名参数
        返回文件(file.Content,file.MimeType);
    }
}


解决方案

在您使用过载文件(字节[]内容,串mime类型,字符串文件名) A 内容处置头会自动添加到与附件的响应,所以你并不需要添加第二次。对于在线您可以使用下面的过载文件(字节[]内容,串mime类型)和手动添加内容处置标题:

  [ActionName(显示文件)]
公共虚拟的ActionResult DisplayFile(GUID FILEID)
{
    var文件= _repos.GetFileInfo(FILEID);
    VAR CD =新ContentDisposition
    {
        内嵌= TRUE,
        文件名= file.Name
    };
    Response.AddHeader(内容处置,cd.ToString());
    返回文件(file.Content,file.MimeType);
}[ActionName(下载文件)]
公共虚拟的ActionResult DownloadFile(GUID FILEID)
{
    var文件= _repos.GetFileInfo(FILEID);
    返回文件(file.Content,file.MimeType,file.Name);
}

We have some files stored in sql database. On an ASP.NET MVC3 form, we display 2 links:

View this file | Download this file

These links go to these corresponding action methods. The download works as expected -- clicking a link forces a save dialog in the browser. However, the display is causing duplicate Content-Disposition headers to be sent to the browser, resulting in an error on Chrome, and an empty page in Firefox.

[ActionName("display-file")]
public virtual ActionResult DisplayFile (Guid fileId, string fileName)
{
    var file = _repos.GetFileInfo(fileId);
    if (file != null)
    {
        Response.AddHeader("Content-Disposition", 
            string.Format("inline; filename={0}", file.Name));
        return File(file.Content, file.MimeType, file.Name);
    }
}

[ActionName("download-file")]
public virtual ActionResult DownloadFile (Guid fileId, string fileName)
{
    var file = _repos.GetFileInfo(fileId);
    if (file != null)
    {
        return File(file.Content, file.MimeType, file.Name);
    }
}

Here are the 2 headers sent to the browser for the display action:

Content-Disposition: inline; filename=name-of-my-file.pdf
Content-Disposition: attachment; filename="name-of-my-file.pdf"

I tried changing my custom content-disposition header to wrap the file name in double quotes, but it still sent 2 headers to the browser. I also tried removing the Content-Disposition header before adding the custom one, but it appears the attachment header is being added after the FileContentResult is returned.

This code used to work. I ran a test just yesterday and noticed it is no longer working in Chrome or Firefox. This could be due to updates in the browsers. IE8 and Safari still open the file correctly.

Update

Thanks again Darin, you are correct. We actually used this approach because of another question you answered.

A little more info about how this was ultimately solved on our end, we have a custom route for the display file link:

context.MapRoute(null,
    "path/to/display-file-attachment/{fileId}/{fileName}",
    new
    {
        area = "AreaName",
        controller = "ControllerName",
        action = "DisplayFile",
    }
);

The hyperlink on the page passes the file name to the action method through the route parameter, so it is already part of the URL. Thus, we did not need to add a custom content-disposition header in order to make the file name match the system's when a user decided to download it (by clicking save icon in browser PDF viewer). So we just used this:

[ActionName("display-file")]
public virtual ActionResult DisplayFile (Guid fileId, string fileName)
{
    var file = _repos.GetFileInfo(fileId);
    if (file != null)
    {
        // no custom content-disposition header, and no 3rd fileName argument
        return File(file.Content, file.MimeType);
    }
}

解决方案

When you use the overload File(byte[] contents, string mimeType, string fileName) a Content-Disposition header is automatically added to the response with attachment, so you don't need to add it a second time. For inline you could use the following overload File(byte[] contents, string mimeType) and manually add the Content-Disposition header:

[ActionName("display-file")]
public virtual ActionResult DisplayFile(Guid fileId)
{
    var file = _repos.GetFileInfo(fileId);
    var cd = new ContentDisposition
    {
        Inline = true,
        FileName = file.Name
    };
    Response.AddHeader("Content-Disposition", cd.ToString()); 
    return File(file.Content, file.MimeType);
}

[ActionName("download-file")]
public virtual ActionResult DownloadFile(Guid fileId)
{
    var file = _repos.GetFileInfo(fileId);
    return File(file.Content, file.MimeType, file.Name);
}

这篇关于如何避免与MVC3 FileContentResult重复的内容处置头?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆