server side printing / PDF conversions using c# and asp.net/wcf service

Hi All,
I know its a tough task to search this kind of  requirement . As i did same and endup with a solution like using Crystal reports for printing on network printer. And a WKHTML library to convert html pages to either images or PDF. There inturn i can convert TIFF files to PDF using Ghostscript(If you need this code please drop a comment).

Now coming to this server side network printing. At first we need to have a following things


  1. Visual studio
  2. Crystal reports for Visual studio
  3. WKHTMLTOPDF/WKHTMLTOIMAGE
  4. A proper permissions on a folder where we are going to store our images or PDF files etc which need to be sent to a printer
And the code flow is first i will scale the image to a standard size with the following code 

prepare a HTML file having image tag with SRC as the image file which needs to be printed then i will call WKHTMLTOIMAGE library  to convert


public static Image ScaleImage(Image image, int maxWidth, int maxHeight)
        {
            var ratioX = (double)maxWidth / image.Width;
            var ratioY = (double)maxHeight / image.Height;
            var ratio = Math.Min(ratioX, ratioY);

            var newWidth = (int)(image.Width * ratio);
            var newHeight = (int)(image.Height * ratio);

            var newImage = new Bitmap(newWidth, newHeight);
            Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
            return newImage;
        }

Then we will prepare a html string and save it to a folder in our directory. The code is as follows

if (ext == "bmp" || ext == "png" || ext == "gif" || ext == "jpg" || ext == "jpeg")
{
filename = ImageDocId + "_" + DateTime.Now.ToString("MMddyyyhhmmssfffff");
filePath = localReportPath + @"Reports\Savedfiles\" + filename;
using (Impersonation impersonation = new Impersonation(impersonationUsername, impersonationDomain, impersonationPWD))
{
 using (Image img = Image.FromFile(file))
 {
  int height = 0;
  int width = 0;

  if (img.Width < 700)
  { width = img.Width; }
  else
  { width = 700; }

  if (img.Height < 700)
  { height = img.Height; }
  else
  { height = 900; }

  Image newImage = ScaleImage(img, width, height);
  newImage.Save(filePath + ".jpg", ImageFormat.Jpeg);
  
 }
}

StringBuilder sb = new StringBuilder();
   sb.AppendLine("<html><body>");
sb.AppendLine("<img alt=\"toprint\" src=\"" + filePath + ".jpg" + "\" width=\"100%\"/>");
sb.AppendLine("</body></html>");
   
if (flag == "3")
{
 ppdf.ImagePath = filePath + ".jpg";
 printtype = "ChartViewImage";// its a report name i used to send to switch case which is not mentioned here
 isSupported = true;
}
else
{                          
 htmlFile = filePath + ".html";
 fs = new FileStream(htmlFile, FileMode.Create, FileAccess.Write);
 writer = new StreamWriter(fs, Encoding.UTF8);
 writer.Write(sb.ToString());
 writer.Close();
 fs.Close();
  

}                         

}

Then to convert to PDF from HTML file generated we will use this code

ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = AppDomain.CurrentDomain.BaseDirectory + @"\bin\wkhtmltopdf.exe";
pdfFile = localReportPath + "\\Reports\\Savedfiles\\" + filename + ".pdf";
//Ref: http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf-0.9.9-doc.html
if (ext == "xml" && filetype == "Visit Summary (CCD)")
{
   startInfo.Arguments = " --minimum-font-size 16 --margin-left 10mm --margin-right 10mm --zoom 3 " + htmlFile + " " + pdfFile;
}
else
{
   startInfo.Arguments = " --margin-left 10mm --margin-right 10mm " + htmlFile + " " + pdfFile;
}
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process p = Process.Start(startInfo);
p.WaitForExit();
p.Dispose();
p.Close();

But for printing Image file we need to use crystal report as follows

if (reportName == "ChartViewImage")
{
#region ChartViewImage

DataTable tempdataTable = new DataTable();
tempdataTable.TableName = "Table";
tempdataTable.Columns.Add("ID", typeof(String));
tempdataTable.Columns.Add("Label", typeof(String));
tempdataTable.Columns.Add("image_path", typeof(String));
tempdataTable.Columns.Add("image_stream", typeof(System.Byte[]));
DataRow dr = tempdataTable.NewRow();

FileStream fs = new FileStream(ImagePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
byte[] Image = new byte[fs.Length];
fs.Read(Image, 0, Convert.ToInt32(fs.Length));
fs.Close();
dr[0] = "1";
dr[1] = "Hello";
dr[2] = ImagePath;
dr[3] = Image;
fs.Close();
tempdataTable.Rows.Add(dr);
string filename = "CVImage" + "_" + DateTime.Now.ToString("MMddyyyhhmmssfffff");

myreport.Load(localReportPath + "\\Reports\\" + "ChartViewImage.rpt");
myreport.Database.Tables[0].ApplyLogOnInfo(GetLogonInfo());

myreport.SetDataSource(tempdataTable);
myreport.Refresh();
myreport.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, localReportPath + "\\Reports\\Savedfiles\\" + filename + ".pdf");
using (Impersonation imp = new Impersonation(impersonationUsername, impersonationDomain, impersonationPWD))
{
 if (!string.IsNullOrEmpty(printerName))
 {
  
  myreport.PrintOptions.PrinterName = printerName;
  
 }
 myreport.PrintToPrinter(copies, false, 0, 0);
}

isSucces = true;
#endregion
}
And here the chartviewimage.rpt need to be prepared by just creating a blob object using a xsd file with dummy table in it. If you need this part too please drop a message.


Thanks for going through my post.

Regards,
Pavan N

Comments

Popular posts from this blog

Download file using WCF REST services

Finding file size in bytes on serverside using c#