November Happy Hour will be moved to Thursday December 5th.
November Happy Hour will be moved to Thursday December 5th.
Hi All, I resolved this by hooking into the page saving event.
The following code will automatically add (
As the page saves:
You could do this onPublish, but I chose onSaving as I wanted the editor/approvers to see exactly what the page would look like.
First install the HTMLAgilityPack from here I just put the dll in the bin folder and referenced it.
Here is the initialization code:
[InitializableModule]
[ModuleDependency(typeof (EPiServer.Web.InitializationModule))]
public class InitializationModule : IInitializableModule
{
public void Initialize(InitializationEngine context)
{
if (!_eventsAttached)
{
DataFactory.Instance.SavingPage += PageSavingPageHandler;
_eventsAttached = true;
}
}
private void PageSavingPageHandler(object sender, PageEventArgs e)
{
// Go through each property looking for xhtmlString properties
foreach (var prop in e.Page.Property)
{
if (prop.PropertyValueType.FullName == "EPiServer.Core.XhtmlString")
{
// Use the HTML agility pack to find links within the HTML
HtmlAgilityPack.HtmlDocument theHtml = new HtmlDocument();
theHtml.LoadHtml(prop.Value.ToString());
var rootVal = theHtml.DocumentNode;
var linksInHtml = rootVal.SelectNodes("//*/a/@href");
if (linksInHtml != null && linksInHtml.Count > 0)
{
foreach (var fullLink in linksInHtml)
{
// Get the link. Internal link is in format:
// link/.aspx?id=
Match match =
new Regex(@"/link/.*?.aspx\?id=([0-9].*)\&").Match(fullLink.Attributes["href"].Value);
var docId = 0;
if (match.Success)
{
int.TryParse(match.Groups[1].Value, out docId);
}
// if we have a document ID then get the document and check extension
if (docId > 0)
{
var contRef = new ContentReference(docId);
var contentRepository = ServiceLocator.Current.GetInstance();
var media = contentRepository.Get(contRef);
var isPdf = media.RouteSegment.ToLower().EndsWith(".pdf");
var isDoc = media.RouteSegment.ToLower().EndsWith(".doc");
var isDocX = media.RouteSegment.ToLower().EndsWith(".docx");
if (isDoc || isPdf || isDocX)
{
// check if it already has a size and type and remove it
// as the link may have been re-linked or the document updated
// having a different size.
fullLink.InnerHtml = Regex.Replace(fullLink.InnerHtml,
@"\([A-Za-z]{3,4} [0-9]*[A-Za-z]{0,2}\)$",
string.Empty);
if (contRef.ID > 0)
{
int size = 0;
if (media.BinaryData!=null)
{
using (var stream = media.BinaryData.OpenRead())
{
size = (int) stream.Length;
}
}
if (size > 0)
{
if (isDoc)
{
fullLink.InnerHtml +=
string.Format(new FileSizeFormatProvider(),
" (DOC {0:fs})", size);
}
else if (isPdf)
{
fullLink.InnerHtml +=
string.Format(new FileSizeFormatProvider(),
" (PDF {0:fs})", size);
}
else
{
fullLink.InnerHtml +=
string.Format(new FileSizeFormatProvider(),
" (DOCX {0:fs})", size);
}
}
}
}
}
}
}
// reset the property value to the new value
e.Page.Property[prop.Name].Value = theHtml.DocumentNode.InnerHtml;
}
}
}
}
Here is the FileSizeFormatProvider class (This is from the net, slightly modified, original and kudos here)
public class FileSizeFormatProvider : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter)) return this;
return null;
}
private const string fileSizeFormat = "fs";
private const Decimal OneKiloByte = 1024M;
private const Decimal OneMegaByte = OneKiloByte * 1024M;
private const Decimal OneGigaByte = OneMegaByte * 1024M;
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (format == null || !format.StartsWith(fileSizeFormat))
{
return defaultFormat(format, arg, formatProvider);
}
if (arg is string)
{
return defaultFormat(format, arg, formatProvider);
}
Decimal size;
try
{
size = Convert.ToDecimal(arg);
}
catch (InvalidCastException)
{
return defaultFormat(format, arg, formatProvider);
}
string suffix;
if (size > OneGigaByte)
{
size /= OneGigaByte;
suffix = "Gb";
}
else if (size > OneMegaByte)
{
size /= OneMegaByte;
suffix = "Mb";
}
else if (size > OneKiloByte)
{
size /= OneKiloByte;
suffix = "Kb";
}
else
{
suffix = "b";
}
return String.Format("{0}" + "{1}", Convert.ToInt32(size), suffix);
}
private static string defaultFormat(string format, object arg, IFormatProvider formatProvider)
{
IFormattable formattableArg = arg as IFormattable;
if (formattableArg != null)
{
return formattableArg.ToString(format, formatProvider);
}
return arg.ToString();
}
}
That's it.
Potentially, a similar method could be used to add other automated content when saving the page.
Hope it helps someone!
Cheers,
Paul
Hi All,
I have a requirement to automatically attach the file type and size to links that are inserted via an editor in an editable area.
For example: change:my link
To: my link (PDF 230kb)
What do you think is the best way to do this?
I've thought of:
All seem to have a lot of negatives!
Can anyone think of a better way?
Cheers,
Paul