2012-02-26 83 views
3

我有一个过程,其中的html存储在数据库中的图像链接。图像也存储在数据库中。我创建了一个从数据库读取图像的控制器动作。我正在生成的路径类似/File/Image?path=Root/test.jpg。 这个图像路径嵌入在HTML中img标签一样<img alt="logo" src="/File/Image?path=Root/001.jpg" />使用itextsharp创建pdf与数据库中的图像

我尝试使用iTextSharp的,以从数据库中读取HTML和创建PDF文档

string _html = GenerateDocumentHelpers.CommissioningSheet(fleetId); 
string _html = GenerateDocumentHelpers.CommissioningSheet(fleetId); 
Document _document = new Document(PageSize.A4, 80, 50, 30, 65); 
MemoryStream _memStream = new MemoryStream(); 
PdfWriter _writer = PdfWriter.GetInstance(_document, _memStream); 
StringReader _reader = new StringReader(_html);    
HTMLWorker _worker = new HTMLWorker(_document); 
_document.Open();    
_worker.Parse(_reader); 
_document.Close(); 
Response.Clear(); 
Response.AddHeader("content-disposition", "attachment; filename=Commissioning.pdf"); 
Response.ContentType = "application/pdf"; 
Response.Buffer = true; 
Response.OutputStream.Write(_memStream.GetBuffer(), 0, _memStream.GetBuffer().Length); 
Response.OutputStream.Flush(); 
Response.End(); 
return new FileStreamResult(Response.OutputStream, "application/pdf"); 

此代码给了我一个非法字符错误。这来自图像标签,它不识别?和=字符,有没有办法,我可以使用img标签呈现这个html,这样当我创建一个pdf时,它将呈现数据库中的html和图像,并创建一个pdf,或者如果itextsharp无法做到这一点,你可以提供给我任何其他可以完成此任务的第三方开源工具?

回答

4

如果图像源不是包含协议的完全限定URL,则iTextSharp假定它是基于文件的URL。解决方案是将所有图像链接转换为绝对格式,格式为http://YOUR_DOMAIN/File/Image?path=Root/001.jpg

您还可以设置工作几乎一样的HTML标签<BASE>的解析器全局属性:

//Create a provider collection to set various processing properties 
System.Collections.Generic.Dictionary<string, object> providers = new System.Collections.Generic.Dictionary<string, object>(); 
//Set the image base. This will be prepended to the SRC so watch your forward slashes 
providers.Add(HTMLWorker.IMG_BASEURL, "http://YOUR_DOMAIN"); 
//Bind the providers to the worker 
worker.SetProviders(providers); 
worker.Parse(reader); 

下面是一个完整的工作C#2010的WinForms应用定位iTextSharp的5.1.2.0演示了如何使用相对图像并使用全局提供程序设置其基础。尽管我通过一堆using声明来确保正确清理,但所有内容都与您的代码非常相似。请确保在所有内容上都观察前导斜杠和尾部斜杠,基本URL只会直接取决于SRC属性,如果未正确完成,您最终可能会出现双斜杠。我在这里硬化了一个域名,但你应该能够轻松使用System.Web.HttpContext.Current.Request对象。

using System; 
using System.IO; 
using System.Windows.Forms; 
using iTextSharp.text; 
using iTextSharp.text.html.simpleparser; 
using iTextSharp.text.pdf; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 

      string html = @"<img src=""/images/home_mississippi.jpg"" />"; 
      string outputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "HtmlTest.pdf"); 
      using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) { 
       using (Document doc = new Document(PageSize.TABLOID)) { 
        using (PdfWriter writer = PdfWriter.GetInstance(doc, fs)) { 
         doc.Open(); 

         using (StringReader reader = new StringReader(html)) { 
          using (HTMLWorker worker = new HTMLWorker(doc)) { 
           //Create a provider collection to set various processing properties 
           System.Collections.Generic.Dictionary<string, object> providers = new System.Collections.Generic.Dictionary<string, object>(); 
           //Set the image base. This will be prepended to the SRC so watch your forward slashes 
           providers.Add(HTMLWorker.IMG_BASEURL, "http://www.vendiadvertising.com"); 
           //Bind the providers to the worker 
           worker.SetProviders(providers); 
           worker.Parse(reader); 
          } 
         } 

         doc.Close(); 
        } 
       } 
      } 

      this.Close(); 
     } 
    } 
} 
+0

谢谢,作品像一个魅力! – user1230089 2012-03-07 22:37:40

+0

@Chris,因为你的代码在“using”里面,是否真的需要doc.Close()? – Alexandre 2014-03-17 21:09:09

+1

你是对的,我只是喜欢我的命令来平衡对方。如果我明确地使用open,那么我想明确地使用close。个人喜好。 – 2014-03-17 21:28:12