Я столкнулся с проблемой отправки файлов, хранящихся в базе данных, обратно пользователю в ASP.NET MVC. То, что я хочу, - это представление, в котором перечислены две ссылки: одна для просмотра файла, и пусть mimetype, отправляемый в браузер, определяет, как он должен обрабатываться, а другая для принудительной загрузки.
Если я выбрал просмотр файла с именем, SomeRandomFile.bak
а в браузере нет соответствующей программы для открытия файлов этого типа, у меня не возникнет проблем с его настройками по умолчанию при загрузке. Однако, если я решу просмотреть файл с именем SomeRandomFile.pdf
или SomeRandomFile.jpg
я хочу, чтобы файл просто открылся. Но я также хочу оставить ссылку для скачивания в стороне, чтобы можно было принудительно вызвать приглашение к загрузке независимо от типа файла. Имеет ли это смысл?
Я пробовал, FileStreamResult
и он работает для большинства файлов, его конструктор не принимает имя файла по умолчанию, поэтому неизвестным файлам присваивается имя файла на основе URL-адреса (который не знает расширение для предоставления на основе типа содержимого). Если я задаю имя файла, указав его, я теряю способность браузера открывать файл напрямую и получаю приглашение на загрузку. кто-нибудь еще сталкивался с этим?
Это примеры того, что я пробовал до сих пор.
//Gives me a download prompt.
return File(document.Data, document.ContentType, document.Name);
//Opens if it is a known extension type, downloads otherwise (download has bogus name and missing extension)
return new FileStreamResult(new MemoryStream(document.Data), document.ContentType);
//Gives me a download prompt (lose the ability to open by default if known type)
return new FileStreamResult(new MemoryStream(document.Data), document.ContentType) {FileDownloadName = document.Name};
Какие-либо предложения?
ОБНОВЛЕНИЕ:
Эти вопросы, кажется, вызывают отклик у многих людей, поэтому я решил опубликовать обновление. Предупреждение о принятом ответе ниже, которое было добавлено Оскаром в отношении международных символов, является полностью действительным, и я ударил его несколько раз из-за использования ContentDisposition
класса. С тех пор я обновил свою реализацию, чтобы исправить это. Хотя приведенный ниже код взят из моего последнего воплощения этой проблемы в приложении ASP.NET Core (Full Framework), он должен работать с минимальными изменениями и в более старом приложении MVC, так как я использую этот System.Net.Http.Headers.ContentDispositionHeaderValue
класс.
using System.Net.Http.Headers;
public IActionResult Download()
{
Document document = ... //Obtain document from database context
//"attachment" means always prompt the user to download
//"inline" means let the browser try and handle it
var cd = new ContentDispositionHeaderValue("attachment")
{
FileNameStar = document.FileName
};
Response.Headers.Add(HeaderNames.ContentDisposition, cd.ToString());
return File(document.Data, document.ContentType);
}
// an entity class for the document in my database
public class Document
{
public string FileName { get; set; }
public string ContentType { get; set; }
public byte[] Data { get; set; }
//Other properties left out for brevity
}
источник
Inline = true
, убедитесь, что НЕ используете 3-х параметрическую перегрузку,File()
которая принимает имя файла в качестве 3-го параметра. Он будет работать в IE, но Chrome сообщит о дублирующем заголовке и откажется представить изображение.У меня возникли проблемы с принятым ответом из-за отсутствия намеков на тип переменной «document»:
var document = ...
поэтому я публикую то, что сработало для меня в качестве альтернативы, на случай, если у кого-то еще возникнут проблемы.источник
AppDomain.CurrentDomain.BaseDirectory
является тоSystem.Web.HttpContext.Current.Server.MapPath("~")
, что это может работать лучше на реальном сервере по сравнению с локальной машиной.Дарин Димитров ответ правильный. Просто дополнение:
Response.AppendHeader("Content-Disposition", cd.ToString());
может привести к сбою в отображении файла в браузере, если ваш ответ уже содержит заголовок «Content-Disposition». В этом случае вы можете использовать:источник
pdf
файл, если я установлю тип содержимого какSystem.Net.Mime.MediaTypeNames.Application.Octet
, он будет принудительно загружаться, даже когда я его установлюInline = true
, но если я установлю какResponse.ContentType = MimeMapping.GetMimeMapping(filePath)
, то естьapplication/pdf
он может открываться правильно, а не загружатьсяResponse.Headers.Add
требуется IIS интегрированный режим конвейера. Кроме того, даже если пул приложений установлен как интегрированный, он выдаст исключение. Решение. ИспользованиеResponse.AddHeader
. См SO нить: stackoverflow.com/questions/22313167/...Для просмотра файла (например, txt):
Чтобы загрузить файл (например, txt):
примечание: чтобы скачать файл, мы должны передать аргумент fileDownloadName
источник
Inline
свойства в Content-Disposition позволяет мне отделить возможность установки имени файла от поведения принудительного скачивания или нет.Я считаю, что этот ответ чище, (на основе https://stackoverflow.com/a/3007668/550975 )
источник
application/octet-stream
и это все равно стало причиной загрузки файла, а не его показа, и, похоже, он совместим.FileVirtualPath -> Исследования \ Global Office Review.pdf
источник
Приведенный ниже код помог мне получить pdf-файл из службы API и отправить его в браузер - надеюсь, это поможет;
источник
Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider
Метод действия должен возвращать FileResult либо с потоком, байтом [], либо с виртуальным путем файла. Вам также необходимо знать тип содержимого загружаемого файла. Вот пример (быстрый / грязный) служебный метод. Пример ссылки на видео Как скачать файлы с использованием ядра asp.net
источник
Если, как и я, вы зашли в эту тему с помощью компонентов Razor, изучая Blazor, то вам придется подумать немного больше, чтобы решить эту проблему. Это немного минное поле, если (как и я) Blazor - ваш первый опыт в мире MVC-типа, поскольку документация не так полезна для таких «черных» задач.
Таким образом, на момент написания статьи вы не можете достичь этого, используя vanilla Blazor / Razor, не встраивая контроллер MVC для обработки части загрузки файла, пример которой приведен ниже:
Затем убедитесь, что запуск вашего приложения (Startup.cs) настроен для правильного использования MVC и содержит следующую строку (добавьте ее, если нет):
.. и, наконец, измените ваш компонент, например, для связи с контроллером (итеративный пример с использованием пользовательского класса):
Надеюсь, это поможет любому, кто изо всех сил (как я!), Получить соответствующий ответ на этот, казалось бы, простой вопрос в сферах Blazor…!
источник