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

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

问题描述

我们有一些文件存储在sql数据库中。在ASP.NET MVC3表单上,我们显示2个链接:



查看此文件|下载此文件



这些链接转到这些相应的操作方法。下载按预期工作 - 点击链接强制浏览器中的保存对话框。但是,显示屏会导致重复的Content-Disposition标头被发送到浏览器,导致Chrome上出现错误,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。名称));
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);
}
}

这是发送到浏览器的2个标题显示操作:

 内容处置:inline; filename = name-of-my-file.pdf 
Content-Disposition:attachment; filename =name-of-my-file.pdf

我尝试更改我的自定义内容配置标题以双引号将文件名包装起来,但仍然向浏览器发送2个标题。在添加自定义头文件之前,我也尝试删除Content-Disposition头文件,但是在返回FileContentResult之后,会显示附件头。



此代码用于工作。我昨天进行了测试,注意到它已经不再适用于Chrome或Firefox。这可能是由于浏览器中的更新。 IE8和Safari仍然正确打开文件。



更新



再次感谢Darin,你是对的。由于您回答的其他问题,我们实际上使用了这种方法。



有关如何最终解决这个问题的更多信息,我们有一个自定义路径来显示文件链接:

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

页面上的超链接通过route参数将文件名传递给action方法,所以它是已经是URL的一部分。因此,我们不需要添加自定义的content-disposition标题,以便在用户决定下载文件名时与文件名匹配(通过单击浏览器PDF查看器中的保存图标)。所以我们只是使用这个:

  [ActionName(display-file)] 
public virtual ActionResult DisplayFile fileId,string fileName)
{
var file = _repos.GetFileInfo(fileId);
if(file!= null)
{
//没有自定义的内容处理头,没有第3个fileName参数
return File(file.Content,file.MimeType);
}
}


解决方案

您使用重载文件(byte [] contents,string mimeType,string fileName) a 内容处理头是自动的添加到附件的响应中,所以您不需要再次添加。对于 inline ,您可以使用以下重载 File(byte [] contents,string mimeType)并手动添加 Content-Disposition 标题:

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


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天全站免登陆