ASP.NET中生成PDF文件


这是看了一下的文章而进行的一个总结,因为最近也在想如何通过程序来生成PDF文件。

Generating PDF files

Reponse有个这样的属性ContentType,获取或设置输出流的 HTTP MIME 类型。通常我们输出的默认形式都是HTML文本格式(text/html),不过如果希望输出的文件类型是javascript类型、CSS样式单类型、JPEG图片类型、Excel类型、Word类型等,都可以进行相应的设置。当然,PDF类型也是可以设置的。

所以当希望输出的文件格式是PDF的时候,可以通过以下的程序设置。

HttpContext.Current.Response.ContentType = "application/pdf"; // Or any other MIME type
HttpContext.Current.Response.AddHeader("content-disposition", "filename=somefilename.pdf");

如果希望输出的文件是以下载的形式展现,那么应该如下

HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=somefilename.pdf");

这篇文章还提到了几个可以参考的PDF生成的控件。

TallPDF.NET(not free)
FOP (open source)
Report.NET (open source)
NPDF (open source)

前言:由于一个客户的项目中需要将WORD文档转换成PDF格式,故写了本篇实站教程

 需求分析:客户的项目以B/S结构为主,提供一个WORD文件在后台自动转换成PDF,经过实际测试,如果该篇WORD文档有100多页的话,转换需要20分钟左右的时间(环境:CPU是奔腾M 1.6G,512M内存),整个CPU的占用率近乎95%~100%,此结果告诉客户以后,客户提议:到客户下班后,自动转换PDF,同时如果使用人确认要查看该PDF文档,如果没有转换,提供给客户选择,是现在转换成PDF,还是由服务器在客户下班后,自动转换。

 项目功能:按需求分析要写两个功能

 第一为:B/S结构后台转换,要提交给客户选择

 第二为:Windows服务自动转换WORD文档到PDF

 这两个分类:核心的转换程序都是采用线程的方式执行,只不过第一个功能是针对一个WORD文件,第二个功能针对所有未转换的WORD文档.

 分析到现在:我们开始实战转换了!

 一:必备工具

 安装必须的工具MS VS.Net2003,MS Office2003,Adobe Acrobat 7.0 Professional,postscript.exe,gs811w32.exe

 MS VS.Net2003的安装不说明

 MS Office2003的安装不说明

 Adobe Acrobat 7.0 Professional安装说明

 运行setup.exe文件,出现输入序列号,就运行注册机,用鼠标在第一行刷下就可以看见序列号,复制粘贴到Adobe Acrobat 7.0 Professional安装程序对话框,安装到最后出现注册时,点击PHONE...将安装程序中显示的第二行序列号(第一行是刚才注册机生成的序列号)复制粘贴到注册机的第二行,点击右边的按钮,再用鼠标刷第三行授权号就出来了,将其复制粘贴到安装程序的最后一行,完成安装注册!

 postscript.exe默认安装就可以了,它是一个PDF转换时所需要的脚本

 gs811w32.exe默认安装就可以,它其实是个PDF虚拟打印机的驱动

 二:配置虚拟打印机

 进入Windows的控制面板,进入打印机,点击"添加打印机"图标.在安装对话框上"按一步",出现选择打印机时,在制造商一栏中选择"Generic",在打印机一栏中,选择"MS Publisher Color Printer",然后一路按下一步,知道安装结束.

 三:开始写第一个程序(脚本程序)

 为什么要使用脚本程序进行转换呢,其实实际测试过程中,使用PDF Distiller的对象引用到C#后,转换成功,但整个PDF Distiller对象不能释放,第二次再转换时,就发生了错误,故此处使用脚本程序实现转换.这样我们只要在C#的程序中调用脚本程序就可以实现WORD到PDF的转换。

 宿主脚本文件名:ConvertDoc2PDF.js

 脚本文件内容:

var files = WScript.Arguments;
var fso = new ActiveXObject("Scripting.FileSystemObject");
var word = new ActiveXObject("Word.Application");
var PDF = new ActiveXObject("PDFDistiller.PDFDistiller.1");
word.ActivePrinter = "MS Publisher Color Printer";

//files(0) 为WORD文档文件名
//files(1) 为,转换后需要保存的路径
//调用fso.GetBaseName(files(0))后,为无路径,无扩展名,的文件名
//files.length为文件参数的个数,使用循环可以支持多个WORD文档的转换

var docfile = files(0);
var psfile = files(1) + fso.GetBaseName(files(0)) + ".ps";
var pdffile = files(1) + fso.GetBaseName(files(0)) + ".pdf";
var logfile = files(1) + fso.GetBaseName(files(0)) + ".log";

try{
var doc = word.Documents.Open(docfile);
//WORD文件转成PS文件;
word.PrintOut(false, false, 0, psfile);
doc.Close(0);

//PS文件转成PDF文件;
PDF.FileToPDF(psfile,pdffile,"");

fso.GetFile(psfile).Delete();//删除PS脚本文件
fso.GetFile(logfile).Delete();//删除转换的日志文件

word.Quit();
WScript.Echo("isuccess");//成功
WScript.Quit(0);
}
catch(x)
{
word.Quit();
WScript.Echo("isfail");//失败
WScript.Quit(0);
}

 然后测试该脚本程序

 启动MS-DOS,输入如下命令:

c:\>cscript //nologo c:\ConvertDoc2PDF.js c:\test.doc c:\

 说明:

 运行成功后将看到test.pdf文档了

 c:\test.doc参数对应的是脚本程序中的files(0)

 c:\参数对应的是脚本程序中的files(1)

 你可以安照该脚本改写成,支持多个参数,使用FOR循环,一次转换多个WORD文档,此处没有使用多个文件转换功能,是考虑到,该段脚本放在C#的线程中执行,这样一来也可以转换多个WORD文档.

 四:使用C#调用ConvertDoc2PDF.js脚本

 新建一个C#的WINDOWS应用程序,添加一个按钮button1

 添加一个函数,函数名StartConvertPDF

public void StartConvertPDF()
{
 Process proc = new Process();
 proc.StartInfo.FileName = "cmd.exe";
 proc.StartInfo.WorkingDirectory = @"c:\";
 proc.StartInfo.CreateNoWindow = true;
 proc.StartInfo.UseShellExecute = false;
 proc.StartInfo.RedirectStandardInput = true; //输入重定向

 proc.Start();
 proc.StandardInput.WriteLine(@"cscript //nologo c:\ConvertDoc2PDF.js c:\test.doc c:\");
 proc.StandardInput.WriteLine("exit");
 proc.WaitForExit();
}

 然后在按钮的CLICK事件中添加调用线程的代码

private void button1_Click(object sender, System.EventArgs e)
{
//定义线程序
Thread thConvert = new Thread(new ThreadStart(StartConvertData));
thConvert.Start();
}

 注意:在测试上面的C#程序时,必须添加如下命名空间

using System.Diagnostics;
using System.Threading;

 五:健壮的C#调用代码(实际考虑,可放在B/S系统中)

 完成第4步的C#测试后,细心的读者,可能看到一点问题,那就是如何得到脚本运行后输出的结果,如何给线程中调用的StartConvertData方法传递参数

 1:传递参数,此话说来也可用一篇教程告诉大家线程中方法如何来传递参数,现在就讲一个方案,此种方案很多,我采用一个类,初始化这个类,然后调用该类的方法作为线程执行的方法

 2:得到脚本的输出结果,使用Process对象的输出重定向,就是说改变输出方向,使脚本不输出到控制台(MS-DOS窗口),而是重定向输出到C#程序中,并采用线程的异步回调方法,显示脚本运行结果。

 添加一个新类,类名为ToPdf

using System;
using System.Diagnostics;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace Doc2Pdf
{
public class ToPdf
{
private string strWord = "";//此处的WORD文件不含路径
private string sPath = "";
public string sExecResult = "";
public bool bSuccess = false;

public ToPdf(string sParamWord,string sParamPath)
{
strWord = sParamWord;
sPath = sParamPath;
}

public void StartConvertPDF()
{
Process proc = new Process();
   proc.StartInfo.FileName = "cmd.exe";
   proc.StartInfo.WorkingDirectory = sPath;
   proc.StartInfo.CreateNoWindow = true;
   proc.StartInfo.UseShellExecute = false;
   proc.StartInfo.RedirectStandardInput = true;//标准输入重定向
proc.StartInfo.RedirectStandardOutput = true;//标准输出重定向

   proc.Start();
proc.StandardInput.WriteLine("cscript //nologo "+sPath+"ConvertDoc2PDF.js "+sPath+strWord+ " "+sPath);
proc.StandardInput.WriteLine("exit");
sExecResult = proc.StandardOutput.ReadToEnd();//返回脚本执行的结果
proc.WaitForExit();
proc.Close();

}

public void EndConvertPDF(System.IAsyncResult ar)//ar参数必须写,是线程执行完成后的回调函数
{
if(sExecResult.IndexOf("isuccess")!=-1)bSuccess=true;
else if(sExecResult.IndexOf("isfail")!=-1)bSuccess=false;
//如果放在B/S系统,你可以在此处写数据库,是成功还是失败,并用一个WEBService程序不断检查数据库,此WEBService程序不放在该回调用函数中
//如果放在C/S系统,回调函数可以不放在类中,以便在窗体程序中调用结果
}
}
}

 改写原来的button1_Click事件中的代码

private void button1_Click(object sender, System.EventArgs e)
{
ToPdf my2Pdf = new ToPdf("test.doc","c:\\");
ThreadStart thStartConvert = new ThreadStart(my2Pdf.StartConvertPDF); //开始异步调用线程
thStartConvert.BeginInvoke(new AsyncCallback(my2Pdf.EndConvertPDF),null);//设置异步线程的回调函数

//如果需要转换多个WORD,你可以用循环
//如果是B/S系统,可以将本段代码放在ASPX中,并结合客户端的无刷新显示数据的技术,不断访问WEBService程序,以确定PDF是否转换成功或失败
}

 六:编写更加健壮的C#调用代码(实际考虑,可放在WINDOWS的服务程序中)

 实际使用时,由于转化PDF时CPU的占用率很高,考虑只在同一时间转换一篇WORD文档,放弃异步线程的回调函数的使用,考虑一个WINDOWS的服务程序。

 写一个函数CheckData2Convert(),不断的检查没有转换的WORD文档,并使用循环调用ToPdf类中执行转换方法StartConvertPDF

//以下给出,泛代码,用户按照自己的需求,填写完整即可
//bool bStart为全局变量,控制循环的进入与退出
//例:18:30开始检查并转换,那么18:30时,bStart=true;并启动转换线程
//6:30停止转换线程,bStart=fasle;

private void CheckData2Convert()
{
//检查指定目录下的没有转换的WORD文档,你同样可以检查数据库中记录的没有转换的WORD文档
string sPath = System.Threading.Thread.GetDomain().BaseDirectory; //当前的路径
while(bStart)
{
int iFileCount = CheckWord(); //CheckWord为一个方法,检查当前没有转换的WORD文档,返回没有转换的文件数,该方法的代码由读者自己编写
for(int i=0;i<iFileCount;i++)
{
string sWord = GetWordFileName(i) //GetWordFileName为一个方法,返回一个不带路径的WORD文件名,该方法的代码由读者自己编写
//ToPdf类中的StartConvertPDF()方法使用的是不带路径的WORD文件名
ToPdf my2Pdf = new ToPdf(sWord ,sPath);
my2Pdf.StartConvertPDF();

if(my2Pdf.sExecResult.IndexOf("isuccess")!=-1)
{
//成功,写日志,或回写数据库
}
else if(my2Pdf.sExecResult.IndexOf("isfail")!=-1)
{
//失败,写日志,或回写数据库
}

}

if(!bStart)break;
Thread.Sleep(1000);
}
}

 然后在服务的开始事件中,启动线程

protected override void OnStart(string[] args)
{
//可以使用一个开始定时器,检查是否到开始时间,时间一到,就开始执行线程,此处的开始执行线程可以放在开始定时事件中
//可以使用一个结束定时器,检查是否到结束时间,时间一到,就结束线程,结束线程的代码可以放在结束定时事件中
//注意:应该使用组件中的定时器,而不是Windows的FORMS中的定时器
//该定时器的类名为System.Timers.Timer,千万别搞错,不然执行不会正常的
bStart = true;
Thread thConvert = new Thread(new ThreadStart(StartConvertData));
thConvert.Start();
}

 然后在服务的结束事件中,设置停止线程的标识bStart= false

protected override void OnStop()
{
bStart = false;
//为何次处不停止线程呢,因为考虑到,现在线程正在转换WORD文档,但没有结束,所以只设置停止标识,转换完成后,线程也执行结束了.
}

 结束语:

 Adobe Acrobat 7.0 Professional,postscript.exe,gs811w32.exe这三个文件可以在itbaby.jss.cn下载,都包含在同一个RAR的压缩文件中了。   

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
asp.net生成PDF详解 asp.net生成PDF PDF详解 用C#制作PDF文件全攻略 丽水市汽车运输集团有限公司信息心 苟安廷 目 录 前 言 3 第一部分 iText的简单应用 4 第一章 创建一个Document 4 第一步 创建一个Document实例: 5 第二步 创建Writer实例 6 第三步 打开Document 6 第四步 添加内容 10 第五步,关闭 document 11 第二章 块、短句和段落 11 块 11 短句 12 段落 12 字体的延续 13 第三章 锚点、列表和注释 14 锚点 14 列表 14 注释 15 第四章 页眉页脚、章节、区域和绘图对象 16 页眉页脚 16 章节和区域 17 图形 17 第五章 表格 18 一些简单的表格 18 一些表格参数 18 大表格 20 内存管理 20 嵌套表格 21 表格偏移 21 表格的绝对位置 21 第六章 图片 21 Image对象 21 图片的位置 22 缩放和旋转图片 23 原始图片数据 23 System.Drawing.Bitmap 23 TIFF和CCITT 24 图片和其他对象 24 第二部分 其他文档格式 25 第七章 XML和 (X)HTML 25 第八章 RTF文件 25 RTF包 25 创建一个RTF文档 25 不支持的特性 26 RTF扩展的页眉和页脚 26 第三部分 iText的高级应用 27 第九章 字体 27 TrueType字体应用 27 TruType字体集合的应用 28 第十章 图象和文本的绝对位置 28 pdfContentByte 28 简单图形 29 文本 29 模板(Form xObjects) 30 分栏 31 PdfTable 32 颜色(SpotColors)和图案(Patterns) 33 第十一章 本地和异地转向、目标和概要 33 本地转向 33 异地转向 33 第十二章 页面和表格事件 34
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值