Asp net core вернуть файл

Обновлено: 04.07.2024

Предпосылки

Перед глубоким погружением в то, как работает модель авторизации на основе установленных правил, рассмотрим модель безопасности на основе ролей, чтобы понять ограничения модели безопасности на основе ролей, а затем узнать, почему следует использовать модель авторизации на основе установленных правил.

public class UserController : Controller

Следующий фрагмент кода может использоваться для ограничения доступа к SecurityController только тем пользователям, которые являются администраторами, то есть тем пользователям, которые являются членами роли администратора.

public class SecurityController : Controller


Несколько ролей

Вы также можете указать несколько ролей, разделенных запятой. Вот пример, который иллюстрирует это.

public class DocumentsController : Controller

В этом примере только те пользователи, которые относятся к роли диспетчера или администратора, могут иметь доступ к DocumentsController и всем его методам.

Обратите внимание, что вы можете применять роли как на уровне контроллера, так и на уровне действий. Например, даже если пользователи с ролями «Manager» или «Administrator» могут получить доступ к DocumentsController и его методам, вы можете захотеть, чтобы к методу этого класса контроллера обращались только пользователи, принадлежащие к роли Администратор. Следующий фрагмент кода показывает, как этого можно достичь.

[Authorize(Roles = "Manager, Administrator")]

public class DocumentsController : Controller

public ActionResult ViewDocument()

public ActionResult DeleteAllDocuments()

Теперь предположим, что вы хотите, чтобы пользователи, которые принадлежат как к ролям менеджера, так и к администратору, имели доступ только к DocumentsController и его методам. В следующем фрагменте кода показано, как можно определить роли таким образом, чтобы пользователи, которые обращаются к DocumentsController и его методам, должны были быть членами как ролей менеджера, так и администратора.

public class DocumentsController : Controller

Необходимость авторизации на основе установленных правил

Авторизация и контроль доступа с использованием ролей для защиты ресурсов от несанкционированного доступа используются уже довольно давно. Тем не менее, они не очень выразительны, и вы можете столкнуться с проблемами, когда количество необходимых ролей очень велико.

Вот сценарий с примером для объяснения. Предположим, вам поручено разработать структуру безопасности для приложения. Первоначально в приложении есть три роли: пользователь, администратор и менеджер. Теперь, если у вас есть несколько вариантов роли администратора, например CustomerAdmin, ReportsAdmin и SuperAdmin, вам придется учитывать каждый из них при разработке инфраструктуры безопасности. Вы также можете иметь несколько вариантов роли менеджера - ваша структура также должна учитывать их. Поскольку количество этих ролей значительно возрастает, становится чрезвычайно сложно эффективно справляться с этими ролями. Именно здесь и появляется модель авторизации на основе установленных правил.

По сути, политика состоит из одного или нескольких требований и обычно регистрируется при запуске приложения в методе ConfigureServices () файла Startup.cs. Чтобы применить политики в ваших контроллерах или методах действий, вы можете воспользоваться атрибутом AuthorizeAttribute или фильтром AuthorizeFilter.

Вы можете создать экземпляр политики, используя класс AuthorizationPolicyBuilder, как показано в приведенном ниже фрагменте кода. Вы можете указать имена ролей, используя метод RequireRole.

var policy = new AuthorizationPolicyBuilder()

Кроме того, вы можете создать экземпляр политики в методе ConfigureServices, как показано в приведенном ниже фрагменте кода.

var policy = new AuthorizationPolicyBuilder()

Вы увидите больше об этом в следующих разделах.

Простого определения установленных правил недостаточно - вы также должны зарегистрировать правила, которые вы определили, с помощью промежуточного программного обеспечения авторизации. Чтобы зарегистрировать политику вы должны указать имя - это имя будет использоваться для ссылки на нее в контроллере или методы действия.

public void ConfigureServices(IServiceCollection services)

Вы также можете указать несколько разрешенных ролей при регистрации политики, как показано в фрагменте кода ниже.

Применение политики

public class SecurityController: Controller

Как видите, вместо указания ролей в атрибуте [Authorize] вы можете указать политику, которую вы хотите применить. Чтобы применить политику к методу действия, вы можете воспользоваться свойством Policy атрибута Authorize, как показано в фрагменте кода ниже.

public IActionResult DeleteAllSecureDocuments()

Вы также можете применить несколько политик к контроллеру или методу действия. Следующий фрагмент кода иллюстрирует, как этого можно достичь.

public class SecurityController : Controller

public ActionResult DeleteUser()

В приведенном выше примере кода вы видите две примененные политики - одну на уровне контроллера, а другую на уровне действий. Обратитесь к методу действия DeleteUser в приведенном выше примере кода. Этот метод действия может быть выполнен только теми пользователями, которые удовлетворяют обеим политикам, а именно ShouldBeEmployeeOnly и Administrator. Другими словами, чтобы вызвать метод DeleteUser, удостоверение должно соответствовать двум политикам ShouldBeEmployeeOnly и Administrator.

Использование авторизации на основе утверждений через политики

Авторизация на основе утверждений обеспечивает декларативный способ проверки доступа к ресурсам. При таком типе авторизации вы обычно проверяете значение утверждения, а затем предоставляете доступ к ресурсу на основе значения, содержащегося в утверждении. Прежде всего, нужно понять, что такое утверждение. Утверждение - это пара ключ-значение, представляющая субъекта, т. е. имя, возраст, номер паспорта, водительское удостоверение, паспорт, национальность, дата рождения и т. д. Таким образом, если dateofbirth является именем утверждения, значением утверждения будет дата рождения, т.е. 1 января 1970 г.

public void ConfigureServices(IServiceCollection services)

Затем вы можете применить эту политику на уровне контроллера к атрибуту AuthorizeAttribute, как показано ниже.

public IActionResult SomeMethod()

//Write your code here

Вы также можете иметь политики с несколькими утверждениями. Вы должны соответствующим образом зарегистрировать их в методе ConfigureServices класса Startup, как показано в приведенном ниже фрагменте кода.

public void ConfigureServices(IServiceCollection services)

Требования

Под покровом используются методы авторизации на основе ролей и утверждений, основанные на требованиях, обработчике и политике. В этом и последующих разделах будет рассмотрен каждый из них.

Требование включает в себя набор параметров данных. Эти параметры данных используются политикой для оценки личности пользователя. Чтобы создать требование, вам нужно создать класс, который реализует интерфейс IAuthorizationRequirement. Следующий фрагмент кода иллюстрирует требование для политики MinimumExp - вы зарегистрируете эту политику через некоторое время.

public class MinimumExpRequirement : IAuthorizationRequirement

public int MinimumExp

public MinimumExpRequirement(int experience)

Обработчики авторизации

Требование может иметь один или несколько обработчиков. Обработчик авторизации используется для оценки свойств требования. Чтобы создать обработчик авторизации, вы должны создать класс, который расширяет AuthorizationHandler <T> и реализует метод HandleRequirementAsync (). Следующий фрагмент кода показывает, как выглядит типичный обработчик авторизации.

public class MinimumExpHandler :

protected override Task HandleRequirementAsync(

throw new NotImplementedException();

В следующем фрагменте кода показано, как можно написать необходимую логику авторизации в методе HandleRequirementsAsync, чтобы найти утверждение и оценить требование.

public class MinimumExpHandler :

protected override Task HandleRequirementAsync(

var claim = context.User.FindFirst("MinExperience");

var expInYears = int.Parse(claim?.Value);

if (expInYears >= requirement.MinimumExp)

Теперь, как узнать, успешно ли выполнен обработчик, то есть что должен вернуть обработчик? Хорошо, если требование было успешно оценено, вы можете вызвать метод Succeed в экземпляре AuthorizationHandlerContext и передать экземпляр требования в качестве параметра методу. В приведенном выше фрагменте кода обратите внимание на то, как был вызван метод Succeed.

Несколько обработчиков для одного требования

Как уже было сказано ранее, требование также может иметь несколько обработчиков. Возможно, вы захотите использовать несколько обработчиков для требования, когда вам нужно оценить требование на основе нескольких условий. Например, вы можете проверить, является ли пользователь сотрудником и возраст работника превышает 50 лет. Таким образом, для каждого из этих условий вам нужен отдельный обработчик.

public class EmployeeRequirement : IAuthorizationRequirement

//Write your code here

public class EmployeeRoleHandler :

//Write your code here to check if the user is an employee

public class MinimumAgeHandler :

//Write your code here to validate min age

Вы должны зарегистрировать обработчиков в коллекции сервисов. Чтобы зарегистрировать обработчик, созданный ранее в этой статье, необходимо написать следующий код в методе ConfigureServices класса Startup, как показано в фрагменте кода ниже.

public void ConfigureServices(IServiceCollection services)

public void ConfigureServices(IServiceCollection services)

Резюме

No Comments

Что такое привязки?

Для начала давайте посмотрим на пример загрузки официального сайта, а затем проведем аутрич-тренинг.Форма официального сайта примерно такая.

Фоновый контроллер определяет метод действия загрузки следующим образом:

Чтобы четко загрузить каталог файлов, мы изменим пример официального сайта.

Через инъекцию, как указано выше private IHostingEnvironment hostingEnv; Чтобы получить путь к корневому каталогу веб-сайта. В форме переднего плана запрашивается отрисовка метода действия следующим образом:

Конечно, не забудьте добавить TagHelper:

При успешной загрузке мы отображаем размер загружаемого байта следующим образом:


Мы можем увидеть загруженные файлы в корневом каталоге веб-сайта следующим образом:


Мы используем объект FormData для получения файла для отправки Ajax следующим образом:

На данный момент необходимо немного изменить фон. Нам больше не нужен интерфейс IFormFile, чтобы получить файл и получить его через форму в запросе, как показано ниже:

Импорт и экспорт Excel


Мы напрямую экспортируем код:


Здесь мы выполняем унифицированную упаковку и экспорт, нужно только установить атрибуты экспорта и данные списка, а именно:


После разговора об экспорте давайте снова посмотрим на импорт. Давайте прочитаем только что импортированные данные и вернемся на страницу:

А сейчас давайте инкапсулируем импорт следующим образом:

Введение подходит к концу. Позвольте мне сказать, что настоящая трудность состоит в том, чтобы не использовать EPPlus для импорта и экспорта. Трудность заключается в пакетном импорте. После пакетного импорта проверяется формат данных. Если указан шаблон импорта, то как обеспечить импорт пакетных данных Формат данных, указанный пользователем, полностью верен, и повторная проверка данных отсутствует. Пакетный импорт в основном завершен за эти два дня. Он примерно разделен на: проверку необходимых данных, проверку формата данных и наличие базы данных. Пользовательский опыт проверки данных и импорта данных - часть формата возврата сбоя импорта. При использовании NPOI и EPPlus для импорта и экспорта таких функций это не может быть проще, но если вы столкнетесь с различными сценариями, как улучшить взаимодействие с пользователем. Это проблема. Если импорт данных не удается, как мы подскажем пользователю? Если в Excel есть раскрывающийся список и объединенные данные ячеек, как нам их получить? Это еще одна проблема. Во многих резюме может говориться, что они будут использовать импорт и экспорт NPOI и EPPlus. На самом деле, их не на что смотреть, это всего лишь инструмент. , Как использовать инструменты для применения к сложным сценам и приводить примеры, которые считаются сложными.

подводить итоги

Могу ли я создать контроллер, который просто возвращает актив изображения?

Контроллер выполнит поиск topbanner.jpg и отправит это изображение обратно клиенту.

Я видел примеры этого, где вы должны создать представление - я не хочу использовать представление. Я хочу сделать все это только с помощью контроллера.

Возможно ли это?

Используйте метод File базовых контроллеров.

  • MVC: 7,6 миллисекунды на фотографию
  • Прямая : 6,7 миллисекунды на фотографию

Примечание. Это среднее время запроса. Среднее значение было рассчитано на основе тысяч запросов на локальном компьютере, поэтому в общее число не должны входить задержки сети или проблемы с пропускной способностью.

Используя релизную версию MVC, я делаю вот что:

У меня, очевидно, есть некоторые специфичные для приложения вещи, касающиеся построения пути, но возвращение FileStreamResult приятно и просто.

Я провел некоторое тестирование производительности в отношении этого действия в отношении вашего ежедневного обращения к изображению (в обход контроллера), и разница между средними значениями составляла всего около 3 миллисекунд (среднее значение для контроллера составляло 68 мс, для неконтроллера было 65 мс).

Я попробовал некоторые из других методов, упомянутых в ответах здесь, и снижение производительности было гораздо более драматичным . некоторые ответы решений были в 6 раз неконтроллерными (другие контроллеры в среднем 340 мс, неконтроллерные 65 мс ).

Чтобы немного расширить ответ Диланда:

Три класса реализуют класс FileResult

Все они довольно понятны:

  • Для загрузки пути к файлу, где файл существует на диске, используйте FilePathResult - это самый простой способ, позволяющий избежать использования потоков .
  • Для массивов byte [] (схожих с Response.BinaryWrite) используйте FileContentResult .
  • Для массивов byte [], в которые вы хотите загрузить файл (расположение содержимого: вложение), используйте FileStreamResult аналогичным образом. ниже, но с MemoryStream и использованием GetBuffer() .
  • Для Streams используйте FileStreamResult . Он называется FileStreamResult, но для него требуется Stream , поэтому я предполагаю , что он работает с MemoryStream литий>

Ниже приведен пример использования метода размещения контента (не тестировался):

Это может быть полезно, если вы хотите изменить изображение перед его возвратом:

Вы можете создать собственное расширение и сделать это следующим образом.

Вы можете написать непосредственно в ответ, но тогда он не поддается проверке. Предпочтительно возвращать ActionResult, который имеет отложенное выполнение. Вот мой повторно используемый StreamResult:

Почему бы не пойти проще и использовать тильду

ОБНОВЛЕНИЕ: есть варианты лучше, чем мой первоначальный ответ. Это хорошо работает вне MVC, но лучше придерживаться встроенных методов возврата содержимого изображения. Смотрите ответы с повышенным голосом.

Вы, конечно, можете. Попробуйте эти шаги:

  1. Загрузить изображение с диска в байтовый массив
  2. кэшируйте изображение в том случае, если вы ожидаете больше запросов на изображение и не хотите дискового ввода-вывода (мой пример не кэширует его ниже)
  3. Измените тип MIME через Response.ContentType
  4. Response.BinaryЗаписать массив байтов изображения

Вот пример кода:

Надеюсь, это поможет!

Решение 1. Рендеринг изображения в представлении по URL-адресу изображения

Вы можете создать свой собственный метод расширения:

Тогда используйте это как:

Решение 2. Рендеринг изображения из базы данных

Создайте метод контроллера, который возвращает данные изображения, как показано ниже

И используйте его в виде:

Чтобы использовать изображение, созданное в результате этого действия в любом HTML, используйте

В приведенном выше фрагменте _db.ImageFiles.Find(uuid) выполняет поиск записи файла изображения в базе данных (контекст EF). Он возвращает объект FileImage, который является просто пользовательским классом, который я создал для модели, а затем использует его как FileContentResult.

Посмотрите на ContentResult. Это возвращает строку, но может быть использовано для создания вашего собственного BinaryResult-подобного класса.

вы можете использовать File для возврата файла, такого как View, Content и т.д.

SomeHelper.EmptyImageResult() должен вернуть FileResult с существующее изображение (например, 1x1 прозрачное).

Это самый простой способ, если у вас есть файлы, хранящиеся на локальном диске. Если файлы byte[] или stream - тогда используйте FileContentResult или FileStreamResult , как предложил Дилан.

Я вижу два варианта:

1) Реализуйте свой собственный IViewEngine и установите свойство ViewEngine используемого вами контроллера в ImageViewEngine желаемым методом «image».

2) Используйте представление :-). Просто измените тип контента и т. Д.

Отказ от ответственности: я не пробовал это, оно основано на просмотре доступных API. : -)

Скачивание файлов из веб

Скачивание распространённая функциональность интерактивных сайтов. Бесчисленное множество файлов различного содержимого скачивается в интернете каждую секунду. Компьютеры, планшеты, смартфоны с разными операционными системами активно участвуют в скачивании файлов.

Функциональность Download - это возможность скачивания файлов с серверной стороны на клиентскую машину. В результате этой операции копия файла, находящегося на сервере, сохраняется на машине клиента.

Способностью отсылать файлы клиентам обладают и HTML статические страницы и конечно же динамические интерактивные сайты. Download гораздо безопасней своей парной операции Upload, когда пользователи загружают, иногда спамовые и вредные, файлы на сервер.

Способы отправки файлов

HTML способ скачивания файлов

Для скачивания файлов HTML тег гиперссылки должен содержать атрибут download. Данный атрибут определяет, что целью гиперссылки будет скачивание файла, но не его открытие в браузере. В атрибуте можно определить желаемое имя скачиваемого файла.

Представление получает через свойство модели ListFiles список файлов доступных для загрузки клиентами сайта. Названия файлов, размер и кнопки загрузки образуют пользовательскую таблицу. Каждая кнопка, ответственная за загрузку файла имеет атрибуты asp-route-, добавляющие в строку запроса два параметра: file - имя файла и mode - способ загрузки. В зависимости от значений этих параметров пользователю веб-страницы отправляется выбранный файл указанным способом. Ниже мы увидим, что веб-страницы шаблона Razor Pages и MVC, за исключением небольших различий, имеют практически одинаковый код.

Таблица списка файлов веб-страницы представления MVC

Методы контроллера для отправки файлов

Унифицированный метод SelectiveResult(. ) выдаёт соответствующий результат в зависимости от значений аргументов: file - имени запрошенного файла и переменной mode, выбранного режима скачивания. Если имя файла равно null, пользователю показывается веб-страница со списком доступных файлов. Если переменная file имеет значение, метод "переключается" на отправку файлов выбранным способом, в зависимости от значения mode.

Листинг action-методов контроллера

Программные коды отправки файлов

Отправка через виртуальный путь

В VirtualDownload(FileInfo fi) главным исполнителем отправки файла клиенту выступает метод File(virtualPath, contentType, fi.Name) возвращающий результат в виде экземпляра класса VirtualFileResult . Данный метод по функциональности одинаков с классическим HTML для скачивания файлов. Указывается виртуальный путь относительно хоста и далее вступают в действие серверная логика отправки контента.

Отправка массива байтов

Отправка открытием потока

HTML код Razor Pages

Интеллектуальный синтаксис Razor гармонично вливается в разметку гипертекста и создаёт пользовательскую таблицу с параметрами для скачивания файлов. Буквально один символ @ выделяет разметку Razor, не нарушая видимую структуру HTML кода. Таблица аналогичная таблицам представлений MVC каркаса, описанного выше. В листинге показан только код формирования списка файлов. В коде разметки также присутствуют asp-атрибуты для однозначного определения выбранного пользователем файла для скачивания.

HTML код страницы Razor Pages.

Метод OnPostAsync Razor Pages

Post-запросы, инициированные кнопками загрузки отлавливает метод OnPostAsync(string file, string mode) класса модели связанного со страницей представления. Данный метод играет роль контроллера: в зависимости от входных данных выдаёт соответствующий результат. Пользователь отправляет POST-запрос с двумя параметрами, на основании аргументов file, mode OnPostAsync(. ) однозначно находит в списке запрошенный файл и вычисляет способ отправки.

Листинг метода OnPostAsync(. )

Буферизация в MemoryStream

Ещё один способ отправки, применённый в коде сайта Razor Pages, использует буферизацию файла в оперативной памяти. Отображение содержимого файла в памяти позволяет веб-приложению на ходу изменять или создавать новый контент по запрошенному названию. Такой вариант отправки имеет недостаток: при значительных размерах файла использование памяти может быть критичным. Но отправка буферизацией в памяти отлично подходит для небольших файлов: изображений, документов и т.п.

Потребление оперативной памяти при буферизации

Использование оперативной памяти при буферизации скачиваемых файлов

Методы отправки BytesDownload(FileInfo fi) и MemorySend(FileInfo fi) используют буферизацию в памяти сервера (см. выше). Данные способы не желательно применять для больших файлов (высказывание относительно и зависит от конфигурации сервера).

Использование память для временного хранения контента сайта может негативно отразиться на работе сайта. На изображении сеанс диагностики среды Visual Studio при скачивании видеофайла размером 1,5 ГБ способами буферизации в памяти. Во время сеанса скачивание потребление оперативки возрастает до 2 ГБ.

Потребление ресурсов без буферизации

Оперативной память без буферизации

Если доверить отправку контента внутренней логике хоста, то скачивание файлов происходит максимально экономно для сервера. Методы VirtualDownload(FileInfo fi) и StreamDownload(FileInfo fi) работают по такому принципу (см. выше).

На скриншоте сеанс диагностики во время отправки видеофайла 1,5 ГБ без буферизации в памяти. Обеспечение скачивания файлов методами VirtualDownload(FileInfo fi) и StreamDownload(FileInfo fi) происходит максимальная экономия аппаратных ресурсов.

Читайте также: