On demand conversion with Word automation services

5. March 2013 13:39 by arnoldbo in SharePoint  //  Tags: , ,   //   Comments

Introduction

In SharePoint 2010 word automation services was introduced the service could be used to do a lot of batch conversion tasks. The implementation had a couple of drawback’s:

  • File generation has to wait for the timer job to execute
  • Can only handle files in SharePoint
  • No feedback when job is done in an easy way

With SharePoint 2013 it is now possible to:

  • Convert documents on the fly
  • Source file doesn’t need to exist in SharePoint
  • Save converted files anywhere you want

The following TechNet article describes the architecture of on demand file conversion: What's new in Word Automation Services for developers

Code download

Download solution

Solution

With the following code examples I want to demonstrate how you can convert files on demand, in the example an word document can be converted on demand to a PDF document.

In the solution the following items are created:

  • Custom action with an Edit Control block
  • Application page were the conversion takes place

Custom action

The custom action should be added to the EditControlBlock and only be available for word documents.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Create custom action in Visual studio:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction
       Id="E0648444-7D5A-4917-875D-C594E4266282.CustomAction"
       RegistrationType="FileType"
       RegistrationId="docx"
       Location="EditControlBlock"
       Sequence="10001"
       Title="Convert to PDF"
       ImageUrl="/_layouts/15/images/icpdf.png">
    <UrlAction Url="javascript:OpenPopUpPageWithTitle('{SiteUrl}/_layouts/Vivens.SP2013.WordServices/WordAutomationConverter.aspx?
      ListId={ListId}&amp;ItemId={ItemId}&amp;ItemUrl={ItemUrl}', RefreshOnDialogClose, 600, 400,'Convert to PDF')"/>
  </CustomAction>
</Elements>

 

Application page

The application page is opened in a dialog window and from this page it is possible to initiate the on demand conversion.

WordAutomationConverter.aspx

<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
    <asp:Panel id="pnlConversion" runat="server">
        <asp:Label ID="lblInputItem" runat="server" Text="Label"></asp:Label>

        <asp:Button ID="btnConvertSharePointFile" runat="server" Text="Save document as PDF" OnClick="btnConvertSharePointFile_Click" />
        <asp:Button ID="btnDownloadAsPdf" runat="server" Text="Download file as PDF" OnClick="btnDownloadAsPdf_Click" />
    </asp:Panel>
    <asp:Panel ID="pnlCompleted" runat="server" Visible="false">
        <asp:Label ID="lblConvertStatus" runat="server" Text="Label"></asp:Label>
        <asp:Button ID="btnReturnToList" runat="server" Text="Return to list" OnClick="btnReturnToList_Click"  />
    </asp:Panel>

</asp:Content>

WordAutomationConverter.aspx.cs

Read the input file in the Page_Load event

        protected void Page_Load(object sender, EventArgs e)
        {
            // Only set up the values the first time the page is loaded
            if (!IsPostBack)
            {
                // Get the input file URL from the query string
                string itemUrl = Request.QueryString["ItemUrl"];
                string inputPath = Site.Url + itemUrl;
                lblInputItem.Text = inputPath;
            }
        }

Convert the document

        protected void btnConvertSharePointFile_Click(object sender, EventArgs e)
        {
            WordAutomationConverterHelper converter = new WordAutomationConverterHelper(SPContext.Current.Site);
            string inputFile = lblInputItem.Text;
            string outputFile = Path.ChangeExtension(lblInputItem.Text, "pdf");

            //Conversion takes place here
            var conversionStatus = converter.ConvertWordDocument(inputFile, outputFile);
            var conversionTime = conversionStatus.CompleteTime.Value.Subtract(conversionStatus.StartTime.Value).Milliseconds.ToString();

            if (conversionStatus.Succeeded)
            {
                lblConvertStatus.Text = string.Format("File converted from <a href='{0}'>{0}</a> to <a href='{1}'>{1}</a>. in {2} milliseconds", inputFile, outputFile, conversionTime);
            }
            else
            {
                lblConvertStatus.Text = string.Format("Something went wrong while converting with message: {0}", conversionStatus.ErrorMessage);
            }
            pnlConversion.Visible = false;
            pnlCompleted.Visible = true;
        }

Download the document

        protected void btnDownloadAsPdf_Click(object sender, EventArgs e)
        {
            WordAutomationConverterHelper converter = new WordAutomationConverterHelper(SPContext.Current.Site);
            string inputFile = lblInputItem.Text;

            byte[] file;
            SPFile document = SPContext.Current.Web.GetFile(lblInputItem.Text);

            var conversionStatus = converter.ConvertWordDocument(document.OpenBinary(), out file);
            if (conversionStatus.Succeeded)
            {
                lblConvertStatus.Text = string.Format("File converted successfully.");
                pnlConversion.Visible = false;
                pnlCompleted.Visible = true;

                Response.Buffer = false; //transmitfile self buffers
                Response.Clear();
                Response.ClearContent();
                Response.ClearHeaders();
                Response.ContentType = "application/pdf";
                Response.AddHeader("Content-Disposition", "attachment; filename=" + Path.ChangeExtension(document.Name, "pdf"));   
                Response.BinaryWrite(file);
                Response.End();
            }
            else
            {
                lblConvertStatus.Text = string.Format("Something went wrong while converting with message: {0}", conversionStatus.ErrorMessage);
            }
        }

WordAutomationConverterHelper

    public class WordAutomationConverterHelper
    {
        private SPSite _site;

        public WordAutomationConverterHelper(SPSite site)
        {
            _site = site;
        }

        /// <summary>
        /// Converts the word document.
        /// </summary>
        /// <param name="inputPath">The input path.</param>
        /// <param name="outPutPath">The out put path.</param>
        /// <returns>Conversion Status.</returns>
        public ConversionItemInfo ConvertWordDocument(string inputPath, string outPutPath) 
        {
            SPServiceContext context = SPServiceContext.GetContext(_site);

            //Get default WordService application
            WordServiceApplicationProxy wordProxy = context.GetDefaultProxy(typeof(WordServiceApplicationProxy)) as WordServiceApplicationProxy;

            //Set the settings for the conversion
            ConversionJobSettings jobSettings = new ConversionJobSettings();
            //SaveFormat.Automatic will try to select the format based on the extension of outPuthPath
            jobSettings.OutputFormat = SaveFormat.Automatic;

            SyncConverter converter = new SyncConverter(wordProxy, jobSettings);
            converter.UserToken = _site.RootWeb.CurrentUser.UserToken;

            ConversionItemInfo result = converter.Convert(inputPath, outPutPath);
            return result;
        }


        /// <summary>
        /// Converts the byte array to PDF.
        /// </summary>
        /// <param name="inputFile">The input file byte array.</param>
        /// <param name="outPutFile">The output file as byte array.</param>
        /// <returns>Conversion Status.</returns>
        public ConversionItemInfo ConvertWordDocument(byte[] inputFile, out byte[] outPutFile)
        {
            SPServiceContext context = SPServiceContext.GetContext(_site);

            //Get default WordService application
            WordServiceApplicationProxy wordProxy = context.GetDefaultProxy(typeof(WordServiceApplicationProxy)) as WordServiceApplicationProxy;

            //Set the settings for the conversion
            ConversionJobSettings jobSettings = new ConversionJobSettings();
            jobSettings.OutputFormat = SaveFormat.PDF;

            SyncConverter converter = new SyncConverter(wordProxy, jobSettings);
            converter.UserToken = _site.RootWeb.CurrentUser.UserToken;

            byte[] convertedFile;
            ConversionItemInfo result = converter.Convert(inputFile, out convertedFile);
            outPutFile = convertedFile;

            return result;
        }
    }

Summary

With the possibility for on demand conversions it is now possible to interact immediately with your users and make it possible to create ad-hoc conversions of your word documents.

blog comments powered by Disqus