Рубрики
ASP.NET

Загрузка файлов ASP.NET MVC пример с использованием Pipeline c использованием бизнес Exception

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

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

Скажем так местами код выглядит просто ужасно нагромождение if «ифок» просто зашкаливает и это только кусок примера, ниже иллюстрация:

Попробуем все это структурировать с помощью подхода pipeline. Создадим класс fileUploadPipeline.

    public class fileUploadPipeline
    {

    }

В конструкторе наш класс будет принимать HttpRequestMessage с которым в дальнейшем мы будем работать.

    public class fileUploadPipeline
    {
        private HttpRequestMessage request;

        public fileUploadPipeline(HttpRequestMessage request)
        {
            this.request = request;
        }
    }

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

        /// <summary>
        /// Проверка токена и получние информации о пользователе
        /// </summary>
        /// <returns></returns>
        internal async System.Threading.Tasks.Task<fileUploadPipeline> ValidateUserAsync()
        {
            var headers = request.Headers;
            if (!headers.Contains("Authorization")) throw new UnauthorizedAccessException("Ошибка доступа");
            var bearer = headers.GetValues("Authorization").FirstOrDefault();
            using(HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("Authorization", bearer);
                var response = await client.PostAsync(ConfigurationManager.AppSettings["apiUrl"] + "User/SecureValidateToken", null);
                var responseString = await response.Content.ReadAsStringAsync();
                answer = JsonConvert.DeserializeObject<AnswerValidateToken>(responseString);
                if(answer.state) return this;
            }
            throw new UnauthorizedAccessException("Ошибка доступа");
        }

Объект AnswerValidateToken содержит данные о пользователе

Пишем метод извлечения файлов из запроса

/// <summary>
        /// Извлечение файлов из запроса
        /// </summary>
        /// <returns></returns>
        internal fileUploadPipeline ExtractFiles()
        {
            foreach (string file in request.Files)
            {
                string extension = System.IO.Path.GetExtension(request.Files[file].FileName).ToLower();
                if (availableFileExtensions.ContainsKey(extension))
                {
                    string mimeType = MimeMapping.GetMimeMapping(System.IO.Path.GetExtension(request.Files[file].FileName));
                    Models.AppFile.TypeFile typeFile = availableFileExtensions[extension];

                    var postedFile = request.Files[file];
                    var NewNameFile = Guid.NewGuid() + extension;
                    var filePath = root + NewNameFile;
                    postedFile.SaveAs(filePath);

                }
            }
            return this;
        }

И вот так прмерно у Вас должен выглядить финальный вариант pipeline загрузки файла от клиента через api микро сервиса. Сразу хочется оговориться это не финальный код Нашей разработки, это 1 из подходов к загрузке файлов используя ASP.NET MVC.

    public class fileUploadPipeline
    {
        #region private variables
        private HttpRequest request;
        private AnswerValidateToken answer;
        private string root = HttpContext.Current.Server.MapPath("~/Uploads/");
        private Dictionary<string, Models.AppFile.TypeFile> availableFileExtensions = new Dictionary<string, Models.AppFile.TypeFile>()
        {
                { ".mp4", MVideo },
        };
        List<Models.AppFile> files = new List<Models.AppFile>();
        #endregion
        /// <summary>
        /// Базовый конструктор
        /// </summary>
        /// <param name="request"></param>
        public fileUploadPipeline(HttpRequest request)
        {
            this.request = request;
        }
        /// <summary>
        /// Проверка токена и получние информации о пользователе
        /// </summary>
        /// <returns></returns>
        internal fileUploadPipeline ValidateUser()
        {
           return Task.Run(async () =>
            {
                var headers = request.Headers;
                if (headers["Authorization"] == null) throw new UnauthorizedAccessException("Ошибка доступа");
                var bearer = headers.GetValues("Authorization").FirstOrDefault();
                using (HttpClient client = new HttpClient())
                {
                    client.DefaultRequestHeaders.Add("Authorization", bearer);
                    var response = await client.PostAsync(ConfigurationManager.AppSettings["apiUrl"] + "User/SecureValidateToken", null);
                    var responseString = await response.Content.ReadAsStringAsync();
                    answer = JsonConvert.DeserializeObject<AnswerValidateToken>(responseString);
                    if (answer.state) return this;
                }
                throw new UnauthorizedAccessException("Ошибка доступа");
            }).Result;
        }
        /// <summary>
        /// Метод проверки есть ли файлы в запросе
        /// </summary>
        /// <returns></returns>
        internal fileUploadPipeline CheckFiles()
        {
            if (request.Files.Count > 0)
            {
                return this;
            }
            throw new NotImplementedException();
        }

        /// <summary>
        /// Извлечение файлов из запроса
        /// </summary>
        /// <returns></returns>
        internal fileUploadPipeline ExtractFiles()
        {
            foreach (string file in request.Files)
            {
                string extension = System.IO.Path.GetExtension(request.Files[file].FileName).ToLower();
                if (availableFileExtensions.ContainsKey(extension))
                {
                    string mimeType = MimeMapping.GetMimeMapping(System.IO.Path.GetExtension(request.Files[file].FileName));
                    Models.AppFile.TypeFile typeFile = availableFileExtensions[extension];

                    var postedFile = request.Files[file];
                    var NewNameFile = Guid.NewGuid() + extension;
                    var filePath = root + NewNameFile;
                    postedFile.SaveAs(filePath);

                }
            }
            return this;
        }

    }

И вызвать этот pipeline в контроллере

public async System.Threading.Tasks.Task<IHttpActionResult> Post()
        {

            try
            {
                var uploadPipe = new Pipelines.fileUploadPipeline(HttpContext.Current.Request)
                    .CheckFiles()
                    .ValidateUser()
                    .ExtractFiles()
                    .isCheckTypeSet();
            }
            catch (UnauthorizedAccessException)
            {
                return Unauthorized();
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
}