Exemplo n.º 1
0
        public async Task <JsonResult> Post(IFormFile formFile)
        {
            DTOTourDetailedModel addedTourDto;

            if (!formFile.FileName.Contains("zip"))
            {
                return new JsonResult("The tour archive file should have .zip type")
                       {
                           StatusCode = StatusCodes.Status400BadRequest
                       }
            }
            ;

            var tempDirectoryPath = Path.Combine(ApplicationConstants.TempDirectoryPath, Guid.NewGuid().ToString());

            Directory.CreateDirectory(tempDirectoryPath);

            var containersNames = new List <string>();

            try
            {
                //Unzip files to temporary directory
                using (var zip = new ZipArchive(formFile.OpenReadStream()))
                {
                    var validEntries = zip.Entries.Where(x => ApplicationConstants.FileNameRegex.IsMatch(x.Name));

                    foreach (var zipEntry in validEntries)
                    {
                        zipEntry.ExtractToFile(Path.Combine(tempDirectoryPath, zipEntry.Name));
                    }
                }

                var tempFiles = Directory.GetFiles(tempDirectoryPath);

                if (!tempFiles.Any(x => x.Contains("config.json")))
                {
                    return new JsonResult("config.json not found")
                           {
                               StatusCode = StatusCodes.Status400BadRequest
                           }
                }
                ;

                //tour config reading and critical fields validation
                var configJson = await System.IO.File.ReadAllTextAsync(tempFiles.First(x => x.Contains("config.json")));

                var config = JsonConvert.DeserializeObject <AddNewTourZipConfig>(configJson);

                var validationErrorMessages = new List <string>();

                if (string.IsNullOrEmpty(config.Name))
                {
                    validationErrorMessages.Add("Name is required");
                }

                if (string.IsNullOrEmpty(config.Description))
                {
                    validationErrorMessages.Add("Description is required");
                }

                if (string.IsNullOrEmpty(config.CountryName))
                {
                    validationErrorMessages.Add("Country name is required");
                }

                if (config.EstimatedDuration.TotalSeconds < 1)
                {
                    validationErrorMessages.Add("Estimated duration is required");
                }

                if (config.GrossPrice.GetValueOrDefault(0) == 0)
                {
                    validationErrorMessages.Add($"GrossPrice should be null or more than 0");
                }

                if (config.Places == null)
                {
                    validationErrorMessages.Add($"Tour places not found");
                }
                else
                {
                    foreach (var place in config.Places)
                    {
                        if (place.AudioTrack == null)
                        {
                            validationErrorMessages.Add($"Audio track file info should not be null");
                        }
                        else if (!tempFiles.Any(x => x.Contains(place.AudioTrack?.FileName)))
                        {
                            validationErrorMessages.Add($"{place.AudioTrack.FileName} file not found");
                        }
                    }
                }

                if (validationErrorMessages.Any())
                {
                    return new JsonResult(validationErrorMessages)
                           {
                               StatusCode = StatusCodes.Status400BadRequest
                           }
                }
                ;

                //upload tour assets to azure blob storage
                var tourAssetsContainerGuid = Guid.NewGuid().ToString().Replace("-", string.Empty);
                var tourAssetsContainerName = $"{config.CountryName.Replace(" ", string.Empty)}-{config.Name.Replace(" ", string.Empty)}-{tourAssetsContainerGuid}";
                tourAssetsContainerName = tourAssetsContainerName.Length > 62 ? tourAssetsContainerName.Substring(0, 62) : tourAssetsContainerName;
                var tourLogoFileName = config.LogoFileName;
                containersNames.Add(tourAssetsContainerName);

                async Task <FileUploadResult> UploadAssetToAsync(string assetFileName, string targetContainerName)
                {
                    var tempFilePath = tempFiles.FirstOrDefault(x => x.Contains(assetFileName));

                    if (tempFilePath == null)
                    {
                        return(new FileUploadResult(false, null, null));
                    }

                    var tempFileName = tempFilePath.Split(Path.DirectorySeparatorChar).LastOrDefault();

                    if (tempFileName == null)
                    {
                        return(new FileUploadResult(false, null, null));
                    }

                    return(await _blobStorageService.UploadFileAsync(targetContainerName, tempFilePath, tempFileName));
                }

                var tourAssetsUploadingResult = await UploadAssetToAsync(tourLogoFileName, tourAssetsContainerName);

                if (!tourAssetsUploadingResult.HasSuccess)
                {
                    return new JsonResult(null)
                           {
                               StatusCode = StatusCodes.Status500InternalServerError
                           }
                }
                ;

                //add tour places to database and upload place assets to azure blob storage
                var dbPlaces = new List <Place>();

                foreach (var place in config.Places)
                {
                    var placeAssetsContainerGuid = Guid.NewGuid().ToString().Replace("-", string.Empty);

                    var placeAssetsContainerName = $"{config.CountryName.Replace(" ", string.Empty)}-{place.Name.Replace(" ", string.Empty)}-{placeAssetsContainerGuid}";
                    placeAssetsContainerName = placeAssetsContainerName.Length > 62 ? placeAssetsContainerName.Substring(0, 62) : placeAssetsContainerName;
                    containersNames.Add(placeAssetsContainerName);

                    var dbPlace = new Place()
                    {
                        Name                = place.Name,
                        Description         = place.Description,
                        Latitude            = place.Latitude,
                        Longitude           = place.Longitude,
                        DisplayName         = place.DisplayName,
                        AssetsContainerName = placeAssetsContainerName
                    };
                    _placesRepository.Create(dbPlace);
                    await _placesRepository.SaveChangesAsync();

                    var audioTrackFileName        = place.AudioTrack.FileName;
                    var audioTrackUploadingResult = await UploadAssetToAsync(audioTrackFileName, placeAssetsContainerName);

                    if (audioTrackUploadingResult.HasSuccess)
                    {
                        var dbAudioAsset = new AudioAsset()
                        {
                            Name               = place.AudioTrack.Name,
                            Description        = place.AudioTrack.Description,
                            AssetContainerName = audioTrackUploadingResult.ContainerName,
                            AssetFileName      = audioTrackUploadingResult.FileName,
                            PlaceId            = dbPlace.PlaceId
                        };
                        _audioAssetsRepository.Create(dbAudioAsset);
                        await _audioAssetsRepository.SaveChangesAsync();
                    }

                    foreach (var image in place.Images)
                    {
                        var imageFileName        = image.FileName;
                        var imageUploadingResult = await UploadAssetToAsync(imageFileName, placeAssetsContainerName);

                        if (imageUploadingResult.HasSuccess)
                        {
                            var dbImageAsset = new ImageAsset()
                            {
                                Name                   = image.Name,
                                Description            = image.Description,
                                PointOfDisplayingStart = image.PointOfDisplayingStart,
                                AssetContainerName     = imageUploadingResult.ContainerName,
                                AssetFileName          = imageUploadingResult.FileName,
                                Place                  = dbPlace
                            };
                            _imageAssetsRepository.Create(dbImageAsset);
                            await _imageAssetsRepository.SaveChangesAsync();
                        }
                    }

                    var placeContainerInfo = _blobStorageService.GetBlobContainerInfo(placeAssetsContainerName);
                    dbPlace.DataSize = placeContainerInfo != null ? placeContainerInfo.TotalBytes : 0;
                    _placesRepository.Update(dbPlace);
                    await _placesRepository.SaveChangesAsync();

                    dbPlaces.Add(dbPlace);
                }

                var  tourContainerInfo = _blobStorageService.GetBlobContainerInfo(tourAssetsContainerName);
                long tourAssetsSize    = tourContainerInfo != null ? tourContainerInfo.TotalBytes : 0;
                tourAssetsSize += dbPlaces.Sum(x => x.DataSize);

                var dbTour = new Tour()
                {
                    Name                = config.Name,
                    Description         = config.Description,
                    CountryName         = config.CountryName,
                    EstimatedDuration   = config.EstimatedDuration,
                    GrossPrice          = config.GrossPrice,
                    DataSize            = tourAssetsSize,
                    AssetsContainerName = tourAssetsUploadingResult.ContainerName,
                    LogoFileName        = tourAssetsUploadingResult.FileName
                };
                _toursRepository.Create(dbTour);
                await _toursRepository.SaveChangesAsync();

                var places = (await _placesRepository.GetAllAsync()).Where(x => dbPlaces.Any(y => y.PlaceId == x.PlaceId));
                foreach (var place in places)
                {
                    place.TourPlaces.Add(new TourPlace()
                    {
                        TourId = dbTour.TourId, PlaceId = place.PlaceId
                    });
                    _placesRepository.Update(place);
                }
                await _placesRepository.SaveChangesAsync();

                var addedTour = await _toursRepository.GetByIdAsync(dbTour.TourId);

                addedTourDto = _tourDTOConverters.DbTourToDTOModel(addedTour);
            }
            catch (Exception ex)
            {
                foreach (var containerName in containersNames)
                {
                    await _blobStorageService.RemoveContainerAsync(containerName);
                }

                return(new JsonResult(ex)
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                });
            }
            finally
            {
                Directory.Delete(tempDirectoryPath, true);
            }

            return(new JsonResult(addedTourDto)
            {
                StatusCode = StatusCodes.Status201Created
            });
        }