Использование Backload для загружаемых файлов в ASP.NET MVC

в 7:31, , рубрики: ASP, asp.net mvc, Веб-разработка, метки:

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

С Javascript’овыми аплоадерами все оказалось очень неплохо – вариантов весьма приличное количество, на все требования и вкусы. А вот с серверными компонентами для реализации бекенда ситуация оказалась несколько хуже. Большая часть решений, которые я нашел, представляла собой небольшие примеры хэндлеров, об которые для реального использования пришлось бы сточить не один напильник.

В итоге, для работы на клиенте был выбран неоднократно обсуждавшийся на хабре jQuery-File-Upload, благо для него есть и angularjs обертка (что было актуально), и, в его документации была обнаружена ссылка на ту реализацию бекенда, о которой я и хотел бы рассказать – Backload.

Backload представляет собой полноценную реализацию бекенда для нескольких js-плагинов для upload’а (включая jquery-file-upload). Проект постоянно развивается, имеет приличный набор настроек и возможностей и позволяет быстро поднять толково работающий механизм для приема загружаемых файлов.

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

Для начала работы достаточно установить пакет Backload из nuget’а или поставить его сразу с jquery-file-upload’ом.
Для самых простых целей – простой установки хватает, достаточно лишь указать для jquery-file-upload нужный URL:

var fileUoloadUrl = "/Backload/UploadHandler";
$('#fileupload').fileupload({
	url: fileUploadUrl
});

И все. Запросы будут обрабатываться встроенным обработчиком.

Для ситуаций, когда этого недостаточно и хочется настроить и кастомизировать процесс более детально – имеется возможность настроить поведение Backload’а с помощью правки конфигурационного файла (.config), либо же влезть в работу обработчика, обрабатывая его события.

Для этого надо создать свой контроллер, и указать jquery-file-upload’у его урл. После чего в своем контроллере создаем экземпляр FileUploadHandler, подписываемся на те из его событий, которые нам нужны и передаем ему обработку.

Пример контроллера с подпиской на события Backload'а
public class FileUploadController : Controller
{
	public async Task<ActionResult> FileHandler()
	{
		FileUploadHandler handler = new FileUploadHandler(Request, this);
		handler.IncomingRequestStarted += handler_IncomingRequestStarted;

		handler.AuthorizeRequestStarted += handler_AuthorizeRequestStarted;
		handler.AuthorizeRequestFinished += handler_AuthorizeRequestFinished;

		handler.GetFilesRequestStarted += handler_GetFilesRequestStarted;
		handler.GetFilesRequestFinished += handler_GetFilesRequestFinished;
		handler.GetFilesRequestException += handler_GetFilesRequestException;

		handler.StoreFileRequestStartedAsync += handler_StoreFileRequestStartedAsync 
		handler.StoreFileRequestFinished += handler_StoreFileRequestFinished;
		handler.StoreFileRequestException += handler_StoreFileRequestException;

		handler.DeleteFilesRequestStarted += handler_DeleteFilesRequestStarted;
		handler.DeleteFilesRequestFinishedAsync += handler_DeleteFilesRequestFinishedAsync; 
		handler.DeleteFilesRequestException += handler_DeleteFilesRequestException;

		handler.OutgoingResponseCreated += handler_OutgoingResponseCreated;

		handler.ProcessPipelineExceptionOccured += handler_ProcessPipelineExceptionOccured;


		ActionResult result = await handler.HandleRequestAsync();
		return result;
	}

	/* обработка событий*/
}

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

Простой пример

async Task handler_StoreFileRequestStartedAsync(object sender, StoreFileRequestEventArgs e)
{
	var fileName = e.Param.FileStatusItem.FileName;
	if (fileName.Equals("some_bad_name.tmp", StringComparison.OrdinalIgnoreCase))
	{
		fileName = "some_good_name.tmp";

		e.Param.FileStatusItem.FileName = fileName;
		e.Param.FileStatusItem.UpdateStatus(true);
	}
}

Или, например, по завершении аплоада что-то сделать с файлом.

Еще один простой пример

void handler_StoreFileRequestFinished(object sender, StoreFileRequestEventArgs e)
{
	var fileName = e.Param.FileStatusItem.FileName;
	var folder = e.Param.FileStatusItem.StorageInfo.FileDirectory;

	DoSomeOperations(folder, fileName);
}

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

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

Автор: Almazen

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js