...

четверг, 5 декабря 2013 г.

[Из песочницы] Использование Backload для загружаемых файлов в 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);
}



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


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

Спасибо за внимание!


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers.


Комментариев нет:

Отправить комментарий