martedì 16 luglio 2013

Create PDF with SharePoint: PDF Helper

Spesso ci troviamo, sviluppando soluzioni SharePoint, ad avere la necessità di convertire documenti Word in formato PDF, inventandoci le peggio soluzioni, utilizzando DLL di terze parti, spendendo migliaia di euro di licenze o addirittura spendendo decine di migliaia di euro per prodotti enterprise (e.g. AdLib).
Beh... visto che siamo di Genova e l'essere tirchi (parsimoniosi direi) è nel nostro DNA, ecco una soluzione a costo ZERO: utilizzare i Word Automation Services di SharePoint.

Ecco un breve esempio di come utilizzare questa funzionalità.

Per mancanza di tempo ho copia incollato il codice da un progetto in essere, lasciando il riferimento ad una classe LoggingHelper non inclusa nell'esempio.
Lascio a voi l'onore di rimuoverle o di implementare la vostra classe di logging.

Fare riferimento a questo post per abilitare il Force del timer job.


using System;
using System.Linq;
using Microsoft.Office.Word.Server.Conversions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace zSiS
{
    public class PdfHelper
    {
        const string WAS = "Word Automation Services";

        private int _TimeOut = 120;

        public int TimeOut
        {
            get { return _TimeOut; }
            set { _TimeOut = value; }
        }

        public DateTime StartDate { get; set; }

        public class ConvertionResult
        {
            public Status Status { get; set; }
            public DateTime UtcStartDate { get; set; }
            public DateTime UtcEndDate { get; set; }
            public string SourceFileName { get; set; }
            public string DestinationFileName { get; set; }
            public double Duration
            {
                get
                {
                    return (UtcEndDate - UtcStartDate).TotalSeconds;
                }
            }
        }

        public enum Status
        {
            Error,
            Success,
            ErrorTimeOut,
            Cancelled
        }

        public ConvertionResult Convert(string sourceFile, string destFile, SPUser user)
        {
            try
            {
                using (new LoggingHelper.LogActivity(sourceFile + " - " + destFile))
                {
                    StartDate = DateTime.UtcNow;

                    ConversionJobSettings jobSettings = new ConversionJobSettings() { OutputFormat = SaveFormat.PDF };

                    ConversionJob pdfConversion = new ConversionJob(WAS, jobSettings) { UserToken = user.UserToken };

                    pdfConversion.AddFile(sourceFile, destFile);
                    pdfConversion.Start();

                    forceTJ(user.ParentWeb.Site.ID);

                    ConversionJobStatus cjsInitial = new ConversionJobStatus(WAS, pdfConversion.JobId, null);

                    while (true)
                    {
                        ConversionJobStatus cjs = new ConversionJobStatus(WAS, pdfConversion.JobId, null);

                        if ((DateTime.UtcNow - StartDate).TotalSeconds > TimeOut)
                            throw new TimeoutException(TimeOut.ToString());

                        if (cjs.Count == cjs.Succeeded + cjs.Failed + cjs.Canceled)
                            break;

                        System.Threading.Thread.Sleep(500);
                    }

                    ConversionJobStatus cjsFinal = new ConversionJobStatus(WAS, pdfConversion.JobId, null);

                    ConvertionResult args = new ConvertionResult() { DestinationFileName = destFile, SourceFileName = sourceFile, Status = Status.Success, UtcEndDate = DateTime.UtcNow, UtcStartDate = StartDate };
                    if (cjsFinal.Canceled > cjsInitial.Canceled)
                        args.Status = Status.Cancelled;
                    else
                        if (cjsFinal.Succeeded > cjsInitial.Succeeded)
                            args.Status = Status.Success;
                        else if (cjsFinal.Failed > cjsInitial.Failed)
                            args.Status = Status.Error;

                    return args;
                }
            }
          
            catch (TimeoutException exto)
            {
                LoggingHelper.LoggingService.Error(LoggingHelper.LoggingService.LoggingServiceCategory.General, exto);
                throw;
            }
            catch (Exception ex)
            {
                LoggingHelper.LoggingService.Error(LoggingHelper.LoggingService.LoggingServiceCategory.General, ex);
                throw;
            }
        }

        private static object Lock = new object();

        private void forceTJ(Guid siteId)
        {
            lock (Lock)
            {
                try
                {

                    using (new LoggingHelper.LogActivity())
                    {
                        SPSecurity.RunWithElevatedPrivileges(delegate()
                           {
                               using (SPSite spSite = new SPSite(siteId))
                               {
                                   bool currentFormDigest = false;
                                   try
                                   {
                                       currentFormDigest = spSite.WebApplication.FormDigestSettings.Enabled;
                                       spSite.WebApplication.FormDigestSettings.Enabled = false;

                                       var service = spSite.WebApplication.Farm.Services.Where(s => s.TypeName.Equals(WAS, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();

                                       if (service == null)
                                           throw new NotSupportedException(WAS + " service does not exist in farm " + spSite.WebApplication.Farm.DisplayName);

                                       var jobDef = service.JobDefinitions.Where(jd => jd.Name.Equals(WAS, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();

                                       if (jobDef == null)
                                           throw new NotSupportedException(WAS + " job definition does not exist in farm ");

                                       if (jobDef.Status == Microsoft.SharePoint.Administration.SPObjectStatus.Online)
                                           jobDef.RunNow();
                                       else
                                           throw new ApplicationException("The job " + jobDef.DisplayName + " is not runnable. It's status is: " + jobDef.Status.ToString());
                                   }
                                   finally
                                   {
                                       spSite.WebApplication.FormDigestSettings.Enabled = currentFormDigest;
                                   }
                               }
                           });

                    }
                }
                catch (Exception ex)
                {
                    LoggingHelper.LoggingService.Low(LoggingHelper.LoggingService.LoggingServiceCategory.General, ex.ToString());
                    if ((DateTime.UtcNow - StartDate).TotalSeconds > TimeOut)
                        throw new TimeoutException(TimeOut.ToString());
                    System.Threading.Thread.Sleep(15000);
                    forceTJ(siteId);
                }
            }
        }
    }
}


Nessun commento:

Posta un commento