С 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, подписываемся на те из его событий, которые нам нужны и передаем ему обработку.
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); }
По данным событиям есть весьма подробное описание в документации и даже примеры их использования. Спектр событий достаточно велик для того, чтобы вмешиваться в процесс именно тогда, когда нужно. В частности, мне очень удобно оказалось реализовать довольно непростую логику определения нужного пути для загрузки файлов, проверки прав на аплоад файлов в конкретные папки, свое ведение лога операций с файлами и добавления к загружаемым файлам файлов с метаданными.
Надеюсь данная статья будет кому-либо полезной и покажет, что есть вполне простые, но удобные решения для работы с загружаемыми файлами.
Спасибо за внимание!
ссылка на оригинал статьи http://habrahabr.ru/post/204878/
Добавить комментарий