public void UpdateFileName(string profile, string path, string fileName) { var cacheKey = GetCacheKey(profile, path); var profileCache = GetProfileCache(profile); string existingFileName; if (profileCache.TryGetValue(cacheKey, out existingFileName) && existingFileName == fileName) { return; } profileCache[cacheKey] = fileName; var profilePart = _imageProfileService.GetImageProfileByName(profile); // profile might not exist in the db if its a dynamic profile if (profilePart != null) { var fileNameRecord = profilePart.FileNames.FirstOrDefault(f => f.Path == path); if (fileNameRecord == null) { fileNameRecord = new FileNameRecord { Path = path, ImageProfilePartRecord = profilePart.Record }; profilePart.FileNames.Add(fileNameRecord); } fileNameRecord.FileName = fileName; } }
protected override DriverResult Editor(ImageProfilePart part, IUpdateModel updater, dynamic shapeHelper) { var currentName = part.Name; var viewModel = new ImageProfileViewModel(); // It would be nice if IUpdateModel provided access to the IsValid property of the Controller, instead of having to track a local flag. var isValid = updater.TryUpdateModel(viewModel, Prefix, null, null); if (String.IsNullOrWhiteSpace(viewModel.Name)) { updater.AddModelError("Name", T("The Name can't be empty.")); isValid = false; } if (currentName != viewModel.Name && _imageProfileService.GetImageProfileByName(viewModel.Name) != null) { updater.AddModelError("Name", T("A profile with the same Name already exists.")); isValid = false; } if (viewModel.Name != viewModel.Name.ToSafeName()) { updater.AddModelError("Name", T("The Name can only contain letters and numbers without spaces")); isValid = false; } if (isValid) { part.Name = viewModel.Name; } return(Editor(part, shapeHelper)); }
public string GetImageProfileUrl(string path, string profileName, ContentItem contentItem, params FilterRecord[] customFilters) { // path is the publicUrl of the media, so it might contain url-encoded chars // try to load the processed filename from cache var filePath = _fileNameProvider.GetFileName(profileName, System.Web.HttpUtility.UrlDecode(path)); bool process = false; //after reboot the app cache is empty so we reload the image in the cache if it exists in the _Profiles folder if (string.IsNullOrEmpty(filePath)) { var profileFilePath = _storageProvider.Combine("_Profiles", FormatProfilePath(profileName, System.Web.HttpUtility.UrlDecode(path))); if (_storageProvider.FileExists(profileFilePath)) { _fileNameProvider.UpdateFileName(profileName, System.Web.HttpUtility.UrlDecode(path), profileFilePath); filePath = profileFilePath; } } // if the filename is not cached, process it if (string.IsNullOrEmpty(filePath)) { Logger.Debug("FilePath is null, processing required, profile {0} for image {1}", profileName, path); process = true; } // the processd file doesn't exist anymore, process it else if (!_storageProvider.FileExists(filePath)) { Logger.Debug("Processed file no longer exists, processing required, profile {0} for image {1}", profileName, path); process = true; } // if the original file is more recent, process it else { DateTime pathLastUpdated; if (TryGetImageLastUpdated(path, out pathLastUpdated)) { var filePathLastUpdated = _storageProvider.GetFile(filePath).GetLastUpdated(); if (pathLastUpdated > filePathLastUpdated) { Logger.Debug("Original file more recent, processing required, profile {0} for image {1}", profileName, path); process = true; } } } // todo: regenerate the file if the profile is newer, by deleting the associated filename cache entries. if (process) { Logger.Debug("Processing profile {0} for image {1}", profileName, path); ImageProfilePart profilePart; if (customFilters == null || !customFilters.Any(c => c != null)) { profilePart = _profileService.GetImageProfileByName(profileName); if (profilePart == null) { return(String.Empty); } } else { profilePart = _services.ContentManager.New <ImageProfilePart>("ImageProfile"); profilePart.Name = profileName; foreach (var customFilter in customFilters) { profilePart.Filters.Add(customFilter); } } // prevent two requests from processing the same file at the same time // this is only thread safe at the machine level, so there is a try/catch later // to handle cross machines concurrency lock (String.Intern(path)) { using (var image = GetImage(path)) { if (image == null) { return(null); } var filterContext = new FilterContext { Media = image, FilePath = _storageProvider.Combine("_Profiles", FormatProfilePath(profileName, System.Web.HttpUtility.UrlDecode(path))) }; var tokens = new Dictionary <string, object>(); // if a content item is provided, use it while tokenizing if (contentItem != null) { tokens.Add("Content", contentItem); } foreach (var filter in profilePart.Filters.OrderBy(f => f.Position)) { var descriptor = _processingManager.DescribeFilters().SelectMany(x => x.Descriptors).FirstOrDefault(x => x.Category == filter.Category && x.Type == filter.Type); if (descriptor == null) { continue; } var tokenized = _tokenizer.Replace(filter.State, tokens); filterContext.State = FormParametersHelper.ToDynamic(tokenized); descriptor.Filter(filterContext); } _fileNameProvider.UpdateFileName(profileName, System.Web.HttpUtility.UrlDecode(path), filterContext.FilePath); if (!filterContext.Saved) { try { var newFile = _storageProvider.OpenOrCreate(filterContext.FilePath); using (var imageStream = newFile.OpenWrite()) { using (var sw = new BinaryWriter(imageStream)) { if (filterContext.Media.CanSeek) { filterContext.Media.Seek(0, SeekOrigin.Begin); } using (var sr = new BinaryReader(filterContext.Media)) { int count; var buffer = new byte[8192]; while ((count = sr.Read(buffer, 0, buffer.Length)) != 0) { sw.Write(buffer, 0, count); } } } } } catch (Exception e) { Logger.Error(e, "A profile could not be processed: " + path); } } filterContext.Media.Dispose(); filePath = filterContext.FilePath; } } } // generate a timestamped url to force client caches to update if the file has changed var publicUrl = _storageProvider.GetPublicUrl(filePath); var timestamp = _storageProvider.GetFile(filePath).GetLastUpdated().Ticks; return(publicUrl + "?v=" + timestamp.ToString(CultureInfo.InvariantCulture)); }
public string GetImageProfileUrl(string path, string profileName, FilterRecord customFilter, ContentItem contentItem) { // try to load the processed filename from cache var filePath = _fileNameProvider.GetFileName(profileName, path); bool process = false; // if the filename is not cached, process it if (string.IsNullOrEmpty(filePath)) { Logger.Debug("FilePath is null, processing required, profile {0} for image {1}", profileName, path); process = true; } // the processd file doesn't exist anymore, process it else if (!_storageProvider.FileExists(filePath)) { Logger.Debug("Processed file no longer exists, processing required, profile {0} for image {1}", profileName, path); process = true; } // if the original file is more recent, process it else { DateTime pathLastUpdated; if (TryGetImageLastUpdated(path, out pathLastUpdated)) { var filePathLastUpdated = _storageProvider.GetFile(filePath).GetLastUpdated(); if (pathLastUpdated > filePathLastUpdated) { Logger.Debug("Original file more recent, processing required, profile {0} for image {1}", profileName, path); process = true; } } } // todo: regenerate the file if the profile is newer, by deleting the associated filename cache entries. if (process) { Logger.Debug("Processing profile {0} for image {1}", profileName, path); ImageProfilePart profilePart; if (customFilter == null) { profilePart = _profileService.GetImageProfileByName(profileName); if (profilePart == null) { return(String.Empty); } } else { profilePart = _services.ContentManager.New <ImageProfilePart>("ImageProfile"); profilePart.Name = profileName; profilePart.Filters.Add(customFilter); } using (var image = GetImage(path)) { var filterContext = new FilterContext { Media = image, FilePath = _storageProvider.Combine("_Profiles", _storageProvider.Combine(profileName, CreateDefaultFileName(path))) }; var tokens = new Dictionary <string, object>(); // if a content item is provided, use it while tokenizing if (contentItem != null) { tokens.Add("Content", contentItem); } foreach (var filter in profilePart.Filters.OrderBy(f => f.Position)) { var descriptor = _processingManager.DescribeFilters().SelectMany(x => x.Descriptors).FirstOrDefault(x => x.Category == filter.Category && x.Type == filter.Type); if (descriptor == null) { continue; } var tokenized = _tokenizer.Replace(filter.State, tokens); filterContext.State = FormParametersHelper.ToDynamic(tokenized); descriptor.Filter(filterContext); } _fileNameProvider.UpdateFileName(profileName, path, filterContext.FilePath); if (!filterContext.Saved) { _storageProvider.TryCreateFolder(_storageProvider.Combine("_Profiles", profilePart.Name)); var newFile = _storageProvider.OpenOrCreate(filterContext.FilePath); using (var imageStream = newFile.OpenWrite()) { using (var sw = new BinaryWriter(imageStream)) { if (filterContext.Media.CanSeek) { filterContext.Media.Seek(0, SeekOrigin.Begin); } using (var sr = new BinaryReader(filterContext.Media)) { int count; var buffer = new byte[8192]; while ((count = sr.Read(buffer, 0, buffer.Length)) != 0) { sw.Write(buffer, 0, count); } } } } } filterContext.Media.Dispose(); filePath = filterContext.FilePath; } } // generate a timestamped url to force client caches to update if the file has changed var publicUrl = _storageProvider.GetPublicUrl(filePath); var timestamp = _storageProvider.GetFile(filePath).GetLastUpdated().Ticks; return(publicUrl + "?v=" + timestamp.ToString(CultureInfo.InvariantCulture)); }