• 动态页面转静态页面+HTML转换PDF+导出PDF


    这几天客户有一个需求:学生的成绩提供打印和导出PDF格式文件两种方法。由于之前没有接触过生成PDF文件,所以在这个上面话了一点时间。下面是这两天的研究成果:

    生成PDF文件在网上有很多资源。大部分是用到ITextSharp。我就省事直接从别人的例子里面拿过来了。

     1  private void CreatPdf()
     2         {
     3             Document doc = new Document(PageSize.A4, 9, 18, 36, 36);//左右上下
     4             MemoryStream ms = new MemoryStream();
     5             try
     6             {
     7                 PdfWriter writer = PdfWriter.GetInstance(doc, ms);
     8                 writer.CloseStream = false;
     9                 doc.Open();
    10                 url =Request.Url.AbsoluteUri;
    11                 Thread thread = new Thread(new ThreadStart(setBitmap));
    12                 thread.SetApartmentState(ApartmentState.STA);
    13                 thread.Start();
    14                 while (thread.IsAlive)
    15                     Thread.Sleep(100);
    16                 bitmap.Save(Server.MapPath("t.bmp"));
    17 
    18                 iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(bitmap, System.Drawing.Imaging.ImageFormat.Bmp);
    19                 img.ScalePercent(75);//560 630
    20                 doc.Add(img);
    21             }
    22             catch (Exception err)
    23             {
    24                 throw new Exception(err.Message);
    25             }
    26             finally
    27             {
    28                 doc.Close();
    29                 using (FileStream fs = new FileStream(Server.MapPath("out.pdf"), FileMode.Create))
    30                 {
    31                     ms.Position = 0;
    32                     byte[] bit = new byte[ms.Length];
    33                     ms.Read(bit, 0, (int)ms.Length);
    34                     fs.Write(bit, 0, bit.Length);
    35                 }
    36                 System.IO.File.Delete(ViewState["pdf"].ToString());
    37                 ViewPdf(ms);
    38             }
    39         }
    40 
    41         private void ViewPdf(Stream fs)
    42         {
    43             Response.Clear();
    44             //中文名的话
    45             //Response.AppendHeader("Content-Disposition", "attachment;filename=" +
    46             //             HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8) + ";charset=GB2312");
    47             Response.AddHeader("Content-Disposition", "attachment;FileName=out.pdf");
    48             Response.AddHeader("Content-Length", fs.Length.ToString());
    49             Response.ContentType = "application/pdf";
    50             long fileLength = fs.Length;
    51             int size = 10240;//10K一--分块下载,10K为1块
    52             byte[] readData = new byte[size];
    53             if (size > fileLength)
    54                 size = Convert.ToInt32(fileLength);
    55             long fPos = 0;
    56             bool isEnd = false;
    57             while (!isEnd)
    58             {
    59                 if ((fPos + size) >= fileLength)
    60                 {
    61                     size = Convert.ToInt32(fileLength - fPos);
    62                     isEnd = true;
    63                 }
    64                 readData = new byte[size];
    65                 fs.Position = fPos;
    66                 fs.Read(readData, 0, size);
    67                 Response.BinaryWrite(readData);
    68                 Response.OutputStream.Flush();
    69                 fPos += size;
    70             }
    71             fs.Close();
    72             Response.OutputStream.Close();
    73             Response.End();//非常重要,没有这句的话,页面的HTML代码将会保存到文件中
    74             Response.Close();
    75         }
    View Code

    最主要的问题是,怎么样把本页面转换成PDF?ITextSharp没有直接把html画到PDF文件的方法。

    首先,有一个想法,那就是把页面转换成图片。再把这个图片加到PDF文件就方便了。

    那么怎么把本页面转换成图片呢?在System.Windows.Forms.WebBrowser类下有一个DrawToBitmap方法,好了,这就简单了。我们创建一个WebBrowser实例,让它把本页面加载进去再画图片就可以了。

     1  public void setBitmap()
     2         {
     3             using (WebBrowser wb = new WebBrowser())
     4             {
     5                 wb.Width = w;
     6                 wb.Height = h;
     7                 wb.ScrollBarsEnabled = false;
     8                 wb.Navigate(ViewState["pdf"].ToString());
     9                 //确保页面被解析完全
    10                 while (wb.ReadyState != WebBrowserReadyState.Complete)
    11                 {
    12                     System.Windows.Forms.Application.DoEvents();
    13                 }
    14                 bitmap = new System.Drawing.Bitmap(w, h);
    15                 wb.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, w, h));
    16                 wb.Dispose();
    17             }
    18         }
    View Code

    这个想法是可以的,在一些不需要登录信息的页面是可用的,可是我想打印的是学生成绩。必须需要登录才拿到成绩信息打印出来。当新建一个WebBrowser再指向成绩页面的时候就没有了登录信息。成为了匿名访问。打印出来的是系统的登录页面。

    解决这个问题的时候我想到了单点登录的方法,但是想想为了一个导出功能用上了单点登录有点大材小用了。就在苦苦思考的时候突然想了起来,既然上面的导出方法对于导出静态页面是有效的,为什么不在点击打印的时候把本页面转换成静态html页面保存在服务器目录上提供导出,再导出之后再删掉呢?

    现在问题又变了,如何导出静态页面呢?这个简单。

     1  protected void Button1_Click(object sender, EventArgs e)
     2         {
     3             //把页面保存成静态页面再导出,这样就不会因为未登录而打印到登陆页面。
     4             //第一步:
     5             string paf = Guid.NewGuid ().ToString();//获取唯一表示。防止多用户并发时导出别人页面。
     6             ViewState["pdf"] = Server.MapPath("~") + paf + "pdf.html";//静态页面的保存路径。为了图片能够显示,Server.MapPath("~")你得改成你相应的文件夹下。
     7             ToHTML("~/PDFForm.aspx?type=pdf", ViewState["pdf"].ToString());//保存静态页面。
     8             //第二部:导出PDF文件
     9             CreatPdf();
    10         }
    11         private void ToHTML(string url, string savefile)
    12         {
    13             StreamWriter sw = new StreamWriter(savefile, false, System.Text.Encoding.GetEncoding("gb2312"));
    14             Server.Execute(url, sw, true);
    15 
    16             sw.Flush();
    17             sw.Close();
    18         }
    View Code

    就在以为大事告成的时候问题出现了,因为是在点击导出按钮的时候生成静态页面,又要访问本页面一次,这就造成了死循环。这次的解决方法是:在生成静态页面的时候带上参数,在Page_Load事件里面把按钮的时间去掉。这就可以了。

     1   private System.Drawing.Bitmap bitmap;
     2         private string url;
     3         private int w = 760, h = 900;
     4         protected void Page_Load(object sender, EventArgs e)
     5         {
     6             if (Request["type"] != null && Request["type"] == "pdf")
     7             {
     8                 Button1.Visible = false;
     9                 Button1.Click -= Button1_Click;//如果没有写,会成为死循环!
    10             }
    11         }
    View Code
  • 相关阅读:
    MyEclipse 修改代码不生效
    最简单的网页分享代码
    php libevent 扩展使用示例
    function gzdecode
    20165327 2017-2018-2 《Java程序设计》第9周学习总结
    结对编程_四则运算
    20165327 2017-2018-2 《Java程序设计》第8周学习总结
    2017-2018-2 20165327 实验二 《Java面向对象程序设计》实验报告
    20165327 2017-2018-2 《Java程序设计》第7周学习总结
    20165327 2017-2018-2 《Java程序设计》第6周学习总结
  • 原文地址:https://www.cnblogs.com/zhoumingxiu/p/3342956.html
Copyright © 2020-2023  润新知