In this post we’ll describe in detail how to invoke this new merging facility from your own code. This demo use C# and .NET, but the web services based interface is identical when used from Java (See this generic PDF Conversion sample)
This post is part of the following series related to manipulating PDF files using web services.
The following sample describes the steps needed to convert all files in a directory, merge the results into a single file and apply page numbering to the merged file using the built in watermarking engine. We are using Visual Studio and C#, but any environment that can invoke web services should be able to access this functionality. Note that the WSDL can be found at http://localhost:41734/Muhimbi.DocumentConverter.WebService/?wsdl. A generic PDF Conversion Java based example is installed alongside the product and discussed in the User & Developer Guide.
using System;
using System.Collections.Generic;
using System.IO;
using System.ServiceModel;
using System.Windows.Forms;
using Simple_PDF_Converter_Sample.ServiceReference1;
namespace Simple_PDF_Converter_Sample
{
public partial class Form1 : Form
{
// ** The URL where the Web Service is located. Amend host name if needed.
string SERVICE_URL = "http://localhost:41734/Muhimbi.DocumentConverter.WebService/";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DocumentConverterServiceClient client = null;
try
{
// ** Options and all settings for batch conversion
ProcessingOptions processingOptions = new ProcessingOptions();
// ** Specify the minimum level of merge settings
MergeSettings mergeSettings = new MergeSettings();
mergeSettings.BreakOnError = false;
mergeSettings.Watermarks = CreateWatermarks();
processingOptions.MergeSettings = mergeSettings;
// ** Get all files in the folder
string sourceFolder = textBox1.Text;
string[] sourceFileNames = Directory.GetFiles(sourceFolder);
// ** Iterate over all files and create a list of SourceFile Objects
List<SourceFile> sourceFiles = new List<SourceFile>();
foreach (string sourceFileName in sourceFileNames)
{
// ** Read the contents of the file
byte[] sourceFileContent = File.ReadAllBytes(sourceFileName);
// ** Set the absolute minimum open options
OpenOptions openOptions = new OpenOptions();
openOptions.OriginalFileName = Path.GetFileName(sourceFileName);
openOptions.FileExtension = Path.GetExtension(sourceFileName);
// ** Set the absolute minimum conversion settings.
ConversionSettings conversionSettings = new ConversionSettings();
conversionSettings.Fidelity = ConversionFidelities.Full;
conversionSettings.Quality = ConversionQuality.OptimizeForPrint;
// ** Create merge settings for each file and set the name for the PDF bookmark
FileMergeSettings fileMergeSettings = new FileMergeSettings();
fileMergeSettings.TopLevelBookmark = openOptions.OriginalFileName;
// ** Create a source file object and add it to the list
SourceFile sourceFile = new SourceFile();
sourceFile.OpenOptions = openOptions;
sourceFile.ConversionSettings = conversionSettings;
sourceFile.MergeSettings = fileMergeSettings;
sourceFile.File = sourceFileContent;
sourceFiles.Add(sourceFile);
}
// ** Assign source files
processingOptions.SourceFiles = sourceFiles.ToArray();
// ** Open the service and configure the bindings
client = OpenService(SERVICE_URL);
// ** Carry out the merge process
BatchResults results = client.ProcessBatch(processingOptions);
// ** Read the results of the merged file.
byte[] mergedFile = results.Results[0].File;
// ** Write the converted file back using the name of the folder
string folderName = new DirectoryInfo(sourceFolder).Name;
DirectoryInfo parentFolder = Directory.GetParent(sourceFolder);
string destinationFileName = Path.Combine(parentFolder.FullName, folderName + ".pdf");
using (FileStream fs = File.Create(destinationFileName))
{
fs.Write(mergedFile, 0, mergedFile.Length);
fs.Close();
}
MessageBox.Show("Contents of directory merged to " + destinationFileName);
}
catch (FaultException<WebServiceFaultException> ex)
{
MessageBox.Show("FaultException occurred: ExceptionType: " +
ex.Detail.ExceptionType.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
CloseService(client);
}
}
/// <summary>
/// Configure the Bindings, endpoints and open the service using the specified address.
/// </summary>
/// <returns>An instance of the Web Service.</returns>
public static DocumentConverterServiceClient OpenService(string address)
{
DocumentConverterServiceClient client = null;
try
{
BasicHttpBinding binding = new BasicHttpBinding();
// ** Use standard Windows Security.
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Windows;
// ** Increase the Timeout to deal with (very) long running requests.
binding.SendTimeout = TimeSpan.FromMinutes(30);
binding.ReceiveTimeout = TimeSpan.FromMinutes(30);
// ** Set the maximum document size to 40MB
binding.MaxReceivedMessageSize = 50 * 1024 * 1024;
binding.ReaderQuotas.MaxArrayLength = 50 * 1024 * 1024;
binding.ReaderQuotas.MaxStringContentLength = 50 * 1024 * 1024;
// ** Specify an identity (any identity) in order to get it past .net3.5 sp1
EndpointIdentity epi = EndpointIdentity.CreateUpnIdentity("unknown");
EndpointAddress epa = new EndpointAddress(new Uri(address), epi);
client = new DocumentConverterServiceClient(binding, epa);
client.Open();
return client;
}
catch (Exception)
{
CloseService(client);
throw;
}
}
/// <summary>
/// Check if the client is open and then close it.
/// </summary>
/// <param name="client">The client to close</param>
public static void CloseService(DocumentConverterServiceClient client)
{
if (client != null && client.State == CommunicationState.Opened)
client.Close();
}
/// <summary>
/// This method creates watermarks for applying page numbers
/// </summary>
/// <returns>Array of watermarks</returns>
private Watermark[] CreateWatermarks()
{
// ** Create watermark container
Watermark pageWatermark = new Watermark();
// ** Set positioning to the lower right of the page
pageWatermark.HPosition = HPosition.Right;
pageWatermark.VPosition = VPosition.Bottom;
// ** Set size
pageWatermark.Width = "200";
pageWatermark.Height = "20";
// ** Create text object for the page numbering
Text oddPageText = new Text();
// ** No need to position the element in the watermark container
oddPageText.Width = "200";
oddPageText.Height = "20";
// ** set content including field codes
oddPageText.Content = "Page {PAGE} of {NUMPAGES}";
// ** set font properties
oddPageText.FillColor = "#ffff0000";
oddPageText.FontFamilyName = "Verdana";
oddPageText.FontSize = "10";
oddPageText.FontStyle = FontStyle.Regular;
//* set text alignment
oddPageText.HAlign = HAlign.Right;
oddPageText.VAlign = VAlign.Top;
//** create array of watermark elements
Element[] pageWatermarkElements = new Element[] { oddPageText };
//** set elements of watermark
pageWatermark.Elements = pageWatermarkElements;
//* return array of watermarks
return new Watermark[] { pageWatermark };
}
}
}
Providing the project and all controls are named as per the steps above, it should compile without errors. Run it, enter the full path to a folder that holds a couple of text files (PDF, Word, Excel, etc) and click the button to start the convert and merge process. The operation may take a while depending on the number and complexity of files in the folder.
Note that In this example we are programmatically configuring the WCF Bindings and End Points. If you wish you can use a declarative approach using the config file.
A more complex and full featured sample application is installed, with full source code, alongside the Conversion Service.
This new functionality is available as of version 5.0 of our software.