У нас есть файлы, хранящиеся в базе данных 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.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);
}
}
Вот 2 заголовка, отправленных браузеру для действия display:
Content-Disposition: inline; filename=name-of-my-file.pdf
Content-Disposition: attachment; filename="name-of-my-file.pdf"
Я попытался изменить свой собственный заголовок Content-Disposition, чтобы заключить имя файла в двойные кавычки, но браузер все равно отправил 2 заголовка. Я также попытался удалить заголовок Content-Disposition перед добавлением настраиваемого, но похоже, что заголовок вложения добавляется после того, как возвращается FileContentResult.
Этот код работал. Буквально вчера я провел тест и заметил, что он больше не работает в Chrome или Firefox. Это могло быть связано с обновлениями в браузерах. IE8 и Safari по-прежнему правильно открывают файл.
Обновление
Еще раз спасибо, Дарин, ты прав. Мы фактически использовали этот подход из-за другого вопроса, на который вы ответили .
Еще немного информации о том, как эта проблема была решена с нашей стороны. У нас есть собственный маршрут для ссылки на файл отображения:
context.MapRoute(null,
"path/to/display-file-attachment/{fileId}/{fileName}",
new
{
area = "AreaName",
controller = "ControllerName",
action = "DisplayFile",
}
);
Гиперссылка на странице передает имя файла методу действия через параметр маршрута, поэтому это уже часть URL-адреса. Таким образом, нам не нужно было добавлять настраиваемый заголовок размещения содержимого, чтобы имя файла соответствовало системному, когда пользователь решил его загрузить (щелкнув значок сохранения в браузере для просмотра PDF-файлов). Итак, мы просто использовали это:
[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);
}
}