diff --git a/src/Umbraco.Core/Models/ContentExtensions.cs b/src/Umbraco.Core/Models/ContentExtensions.cs index 9f83eaca5c..c76377dc6e 100644 --- a/src/Umbraco.Core/Models/ContentExtensions.cs +++ b/src/Umbraco.Core/Models/ContentExtensions.cs @@ -1,6 +1,14 @@ using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.IO; using System.Linq; +using System.Web; +using System.Xml; using System.Xml.Linq; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.UnitOfWork; @@ -45,6 +53,283 @@ namespace Umbraco.Core.Models } } + /// + /// Sets and uploads the file from a HttpPostedFileBase object as the property value + /// + /// to add property value to + /// Alias of the property to save the value on + /// The containing the file that will be uploaded + public static void SetValue(this IMedia media, string propertyTypeAlias, HttpPostedFileBase value) + { + var name = + IOHelper.SafeFileName( + value.FileName.Substring(value.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, + value.FileName.Length - value.FileName.LastIndexOf(IOHelper.DirSepChar) - 1) + .ToLower()); + + if(string.IsNullOrEmpty(name) == false) + SetFileOnContent(media, propertyTypeAlias, name, value.InputStream); + } + + /// + /// Sets and uploads the file from a HttpPostedFile object as the property value + /// + /// to add property value to + /// Alias of the property to save the value on + /// The containing the file that will be uploaded + public static void SetValue(this IMedia media, string propertyTypeAlias, HttpPostedFile value) + { + var name = + IOHelper.SafeFileName( + value.FileName.Substring(value.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, + value.FileName.Length - value.FileName.LastIndexOf(IOHelper.DirSepChar) - 1) + .ToLower()); + + if (string.IsNullOrEmpty(name) == false) + SetFileOnContent(media, propertyTypeAlias, name, value.InputStream); + } + + /// + /// Sets and uploads the file from a HttpPostedFileWrapper object as the property value + /// + /// to add property value to + /// Alias of the property to save the value on + /// The containing the file that will be uploaded + public static void SetValue(this IMedia media, string propertyTypeAlias, HttpPostedFileWrapper value) + { + if (string.IsNullOrEmpty(value.FileName) == false) + SetFileOnContent(media, propertyTypeAlias, value.FileName, value.InputStream); + } + + /// + /// Sets and uploads the file from a HttpPostedFileBase object as the property value + /// + /// to add property value to + /// Alias of the property to save the value on + /// The containing the file that will be uploaded + public static void SetValue(this IContent content, string propertyTypeAlias, HttpPostedFileBase value) + { + var name = + IOHelper.SafeFileName( + value.FileName.Substring(value.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, + value.FileName.Length - value.FileName.LastIndexOf(IOHelper.DirSepChar) - 1) + .ToLower()); + + if (string.IsNullOrEmpty(name) == false) + SetFileOnContent(content, propertyTypeAlias, name, value.InputStream); + } + + /// + /// Sets and uploads the file from a HttpPostedFile object as the property value + /// + /// to add property value to + /// Alias of the property to save the value on + /// The containing the file that will be uploaded + public static void SetValue(this IContent content, string propertyTypeAlias, HttpPostedFile value) + { + var name = + IOHelper.SafeFileName( + value.FileName.Substring(value.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, + value.FileName.Length - value.FileName.LastIndexOf(IOHelper.DirSepChar) - 1) + .ToLower()); + + if (string.IsNullOrEmpty(name) == false) + SetFileOnContent(content, propertyTypeAlias, name, value.InputStream); + } + + /// + /// Sets and uploads the file from a HttpPostedFileWrapper object as the property value + /// + /// to add property value to + /// Alias of the property to save the value on + /// The containing the file that will be uploaded + public static void SetValue(this IContent content, string propertyTypeAlias, HttpPostedFileWrapper value) + { + if (string.IsNullOrEmpty(value.FileName) == false) + SetFileOnContent(content, propertyTypeAlias, value.FileName, value.InputStream); + } + + private static void SetFileOnContent(IContentBase content, string propertyTypeAlias, string name, Stream fileStream) + { + var property = content.Properties.FirstOrDefault(x => x.Alias == propertyTypeAlias); + if(property == null) + return; + + bool supportsResizing = false; + string fileName = UmbracoSettings.UploadAllowDirectories + ? Path.Combine(property.Id.ToString(), name) + : property.Id + "-" + name; + string extension = Path.GetExtension(name); + + var fs = FileSystemProviderManager.Current.GetFileSystemProvider(); + fs.AddFile(fileName, fileStream); + + //Check if file supports resizing and create thumbnails + if (("," + UmbracoSettings.ImageFileTypes + ",").Contains(string.Format(",{0},", extension))) + { + supportsResizing = true; + + // Make default thumbnail + var thumbUrl = Resize(fs, fileName, extension, 100, "thumb"); + + //Look up Prevalues for this upload datatype - if it is an upload datatype + var uploadFieldId = new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c"); + if (property.PropertyType.DataTypeControlId == uploadFieldId) + { + //Get Prevalues by the DataType's Id: property.PropertyType.DataTypeId + //var definition = ApplicationContext.Current.Services.DataTypeService.GetDataTypeDefinitionById(property.PropertyType.DataTypeId); + } + } + + //Check for auto fill of additional properties + if (UmbracoSettings.ImageAutoFillImageProperties != null) + { + XmlNode uploadFieldConfigNode = + UmbracoSettings.ImageAutoFillImageProperties.SelectSingleNode( + string.Format("uploadField [@alias = \"{0}\"]", propertyTypeAlias)); + + if (uploadFieldConfigNode != null) + { + // Only add dimensions to web images + if (supportsResizing) + { + SetPropertyValue(content, uploadFieldConfigNode, "widthFieldAlias", GetDimensions(fs, fileName).Item1); + SetPropertyValue(content, uploadFieldConfigNode, "heightFieldAlias", GetDimensions(fs, fileName).Item2); + } + else + { + SetPropertyValue(content, uploadFieldConfigNode, "widthFieldAlias", string.Empty); + SetPropertyValue(content, uploadFieldConfigNode, "heightFieldAlias", string.Empty); + } + + SetPropertyValue(content, uploadFieldConfigNode, "lengthFieldAlias", fs.GetSize(fileName)); + SetPropertyValue(content, uploadFieldConfigNode, "extensionFieldAlias", extension); + } + } + + //Set the value of the property to that of the uploaded file's url + property.Value = fs.GetUrl(fileName); + } + + private static void SetPropertyValue(IContentBase content, XmlNode uploadFieldConfigNode, string propertyAlias, object propertyValue) + { + XmlNode propertyNode = uploadFieldConfigNode.SelectSingleNode(propertyAlias); + if (propertyNode != null && string.IsNullOrEmpty(propertyNode.FirstChild.Value) == false) + { + content.SetValue(propertyNode.FirstChild.Value, propertyValue); + } + } + + private static string Resize(MediaFileSystem fileSystem, string path, string extension, int maxWidthHeight, string fileNameAddition) + { + var fileNameThumb = DoResize(fileSystem, path, extension, GetDimensions(fileSystem, path).Item1, GetDimensions(fileSystem, path).Item2, maxWidthHeight, fileNameAddition); + + return fileSystem.GetUrl(fileNameThumb); + } + + private static Tuple GetDimensions(MediaFileSystem fileSystem, string path) + { + var fs = fileSystem.OpenFile(path); + var image = Image.FromStream(fs); + var fileWidth = image.Width; + var fileHeight = image.Height; + fs.Close(); + image.Dispose(); + + return new Tuple(fileWidth, fileHeight); + } + + private static string DoResize(MediaFileSystem fileSystem, string path, string extension, int width, int height, int maxWidthHeight, string fileNameAddition) + { + var fs = fileSystem.OpenFile(path); + var image = Image.FromStream(fs); + fs.Close(); + + string fileNameThumb = String.IsNullOrEmpty(fileNameAddition) ? + string.Format("{0}_UMBRACOSYSTHUMBNAIL.jpg", path.Substring(0, path.LastIndexOf("."))) : + string.Format("{0}_{1}.jpg", path.Substring(0, path.LastIndexOf(".")), fileNameAddition); + + var thumb = GenerateThumbnail(fileSystem, + image, + maxWidthHeight, + width, + height, + path, + extension, + fileNameThumb, + maxWidthHeight == 0); + + fileNameThumb = thumb.Item3; + + image.Dispose(); + + return fileNameThumb; + } + + private static Tuple GenerateThumbnail(MediaFileSystem fileSystem, Image image, int maxWidthHeight, int fileWidth, + int fileHeight, string fullFilePath, string extension, + string thumbnailFileName, bool useFixedDimensions) + { + // Generate thumbnail + float f = 1; + if (!useFixedDimensions) + { + var fx = (float)image.Size.Width / (float)maxWidthHeight; + var fy = (float)image.Size.Height / (float)maxWidthHeight; + + // must fit in thumbnail size + f = Math.Max(fx, fy); //if (f < 1) f = 1; + } + + var widthTh = (int)Math.Round((float)fileWidth / f); int heightTh = (int)Math.Round((float)fileHeight / f); + + // fixes for empty width or height + if (widthTh == 0) + widthTh = 1; + if (heightTh == 0) + heightTh = 1; + + // Create new image with best quality settings + var bp = new Bitmap(widthTh, heightTh); + var g = Graphics.FromImage(bp); + g.SmoothingMode = SmoothingMode.HighQuality; + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + g.CompositingQuality = CompositingQuality.HighQuality; + + // Copy the old image to the new and resized + var rect = new Rectangle(0, 0, widthTh, heightTh); + g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel); + + // Copy metadata + var imageEncoders = ImageCodecInfo.GetImageEncoders(); + ImageCodecInfo codec = null; + if (extension.ToLower() == "png" || extension.ToLower() == "gif") + codec = imageEncoders.Single(t => t.MimeType.Equals("image/png")); + else + codec = imageEncoders.Single(t => t.MimeType.Equals("image/jpeg")); + + + // Set compresion ratio to 90% + var ep = new EncoderParameters(); + ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L); + + // Save the new image using the dimensions of the image + string newFileName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", + string.Format("{0}x{1}", widthTh, heightTh)); + var ms = new MemoryStream(); + bp.Save(ms, codec, ep); + ms.Seek(0, 0); + + fileSystem.AddFile(newFileName, ms); + + ms.Close(); + bp.Dispose(); + g.Dispose(); + + return new Tuple(widthTh, heightTh, newFileName); + } + /// /// Gets the for the Creator of this content. /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 631d84345d..c016413e76 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -54,6 +54,7 @@ False ..\..\lib\SQLCE4\System.Data.SqlServerCe.Entity.dll +