2016-06-28 127 views
3

我使用的是從html字符串生成pdf的itext-5.3.4.jar和xmlworker-1.2.1.jar庫,html包含圖像標誌和內聯css。使用itext從Html字符串與圖像和css生成PDF的Android

我的html文件和圖像是在資產文件夾中,使用這個庫我的pdf生成成功,但沒有圖像顯示,也沒有css風格。任何人有一個建議我應該怎麼做才能解決這個問題,如果任何其他庫或任何其他選項從HTML生成PDF將有所幫助。

我使用這些功能生成PDF:

public static void generatePdfFromHtlm(String fileName, String htmlString){ 


    try { 
     File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), AppConfig.getContext().getPackageName() + "/" + "Pdf"); 

     if (!mediaStorageDir.exists()) { 
      mediaStorageDir.mkdirs(); 
     } 

     File fileWithinMyDir = new File(mediaStorageDir, fileName); 

     FontFactory.registerDirectories(); 
     Document document = new Document(PageSize.A4); 
     PdfWriter writer = PdfWriter.getInstance(document, 
       new FileOutputStream(fileWithinMyDir)); 
     document.open(); 
     HtmlPipelineContext htmlContext = new HtmlPipelineContext(null); 
     htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory()); 
     htmlContext.setImageProvider(new AbstractImageProvider() { 
      public String getImageRootPath() { 

       Uri uri = Uri.parse("file:///android_asset/"); 

       String newPath = uri.toString(); 

       return newPath; 
      } 
     }); 


     CSSResolver cssResolver = 
       XMLWorkerHelper.getInstance().getDefaultCssResolver(false); 
     /*Pipeline<?> pipeline = 
       new CssResolverPipeline(cssResolver, 
         new HtmlPipeline(htmlContext, 
           new PdfWriterPipeline(document, writer)));*/ 

     // Pipelines 
     PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer); 
     HtmlPipeline html = new HtmlPipeline(htmlContext, pdf); 
     CssResolverPipeline css = new CssResolverPipeline(cssResolver, html); 

     XMLWorker worker = new XMLWorker(css, true); 

     XMLParser p = new XMLParser(worker); 
     InputStream is = new ByteArrayInputStream(htmlString.getBytes()); 
     p.parse(is); 

     document.close(); 


    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

我的html文件是

<!DOCTYPE html> 
 
<!--[if IE 8]> <html lang="en" class="ie8"> <![endif]--> 
 
<!--[if IE 9]> <html lang="en" class="ie9"> <![endif]--> 
 
<!--[if !IE]><!--> 
 
<html lang="en"> <!--<![endif]--> 
 

 
<!-- BEGIN HEAD --> 
 
<head> 
 
    <meta charset="utf-8" /> 
 
    
 
    <title>WeighInsheet</title> 
 
    
 
    
 
    <style type="text/css"> 
 
    
 
    body { font-family:Arial; } 
 
     .Wrapper { border:1px solid #cccccc; height:auto; margin:0px 65px;} 
 
     .header { height:105px; margin:5px; float:left;} 
 
     .logo { width:100px; height:100px; float:left; } 
 
    .heading { width:600px;} 
 
    h2{ margin:40px 0px 0px 0px;font-size: 22px; font-weight:bold;} 
 
    h3{ margin:0px; font-weight:normal;font-size: 16px;} 
 
    table { border-collapse: collapse; border-spacing: 0; width:100%; } 
 
    table td { font-family: arial; font-size: 14px; padding: 10px 5px; border: 1px solid #ddd; } 
 
    table th { background-color:#000000; color:#ffffff; font-family: arial; font-size: 16px; font-weight: bold; 
 
      border: 1px solid #ddd; } 
 
    
 
    </style> 
 

 

 
</head> 
 

 
<!-- END HEAD --> 
 

 
<!-- BEGIN BODY --> 
 

 
<body> 
 
    
 
<div class="Wrapper"> 
 

 
<div class="header"> 
 

 
<div class="logo"><img src="logo.jpg" class="logo"/></div> 
 

 
<div class="heading" align="center"> 
 
<h2>Description</h2> 
 
<h3>Title Meta</h3> 
 
</div> 
 

 
</div> 
 
<table> 
 

 
<thead> 
 
##CHANGEHEADER## 
 
</thead> 
 

 
<tbody> 
 
    ##CHANGEBODY## 
 
</tbody> 
 

 
</table> 
 

 
</div> 
 

 
</body> 
 

 
<!-- END BODY --> 
 

 
</html>

我的圖像文件「logo.jpg」被在資產文件夾中。

+1

爲什麼不使用Android端口iTextG?爲什麼不使用當前版本5.5.9? –

+0

java.lang。NoSuchMethodError:無虛方法addCell(Lcom/itextpdf/text/pdf/PdfPCell;)類Lcom/itextpdf/text/pdf/PdfPTable中的V;或它的超類('com.itextpdf.text.pdf.PdfPTable'聲明出現在/data/app/com.test.pdfgenerate-1/base.apk) –

+0

它會在更新後給我這個錯誤itext 5.5.9 –

回答

2

我已經修復了使用Xml Worker類生成問題的問題。

對於Css不起作用創建外部css文件並應用它,

for ex。

InputStream is = new ByteArrayInputStream(aHtmlString.getBytes()); 
          InputStream css = new ByteArrayInputStream(cssString.getBytes()); 

          XMLWorkerHelper.getInstance().parseXHtml(writer, document, is, css); 

對於圖像顯示問題複製圖像從資產文件夾到手機內部文件夾。

添加您的img標籤到該文件夾​​圖像路徑。

例如,

<img src="/storage/emulated/0/MyApp/Images/my_logo.jpg"/> 

使用這種方法複製文件從資產到文件夾。

public static void listAssetFiles(String path,Context ctx,String folderPath) { 

    String [] list; 
    try { 
     list = ctx.getAssets().list(path); 
     if (list.length > 0) { 
      // This is a folder 
      for (String file : list) { 

       copyIntoFolder(file,ctx,path+"/",folderPath); 
      } 
     } 
    } catch (IOException e) { 

    } 



} 

public static void copyIntoFolder(String fileName, Context ctx, String filePath, String folderPath){ 
    AssetManager assetManager = ctx.getAssets(); 
    InputStream in = null; 
    OutputStream out = null; 
    try { 
     in = assetManager.open(filePath+fileName); 
     File outFile = new File(folderPath , fileName); 
     out = new FileOutputStream(outFile); 
     Utility.copyFile(in, out); 
     in.close(); 
     // in = null; 
     out.flush(); 
     out.close(); 
     //out = null; 
    } catch(IOException e) { 
     Log.e("IOException", "copyIntoFolder: ",e); 

    } 
} 

iText的犯規支持下的所有CSS屬性是支載的CSS屬性的列表,根據創建該支持的CSS屬性您的HTML。

Css Support

+0

你是否從html文件中刪除了css部分?我的頭文件中含有css的html文件,無法應用它! –

+0

是的,我已經使用CSS在HTML標題內嵌 –

1

iText的夏普不支持所有的CSS property.You可以在web視圖加載HTML和使用此代碼生成PDF。

private void createWebPrintJob(WebView webView) { 

     try { 
      PrintDocumentAdapter printAdapter; 
      String jobName = getString(R.string.app_name) + " Document"; 
      PrintAttributes attributes = new PrintAttributes.Builder() 
        .setMediaSize(PrintAttributes.MediaSize.ISO_A4) 
        .setResolution(new PrintAttributes.Resolution("pdf", "pdf", 600, 600)) 
        .setMinMargins(PrintAttributes.Margins.NO_MARGINS).build(); 
      File path = new File(Environment.getExternalStorageDirectory() 
        .getAbsolutePath() + "/AamirPDF/"); 


      path.mkdirs(); 
      PdfPrint pdfPrint = new PdfPrint(attributes); 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
       printAdapter = webView.createPrintDocumentAdapter(jobName); 
      } else { 
       printAdapter = webView.createPrintDocumentAdapter(); 
      } 


      pdfPrint.printNew(printAdapter, path, "output_" + System.currentTimeMillis() + ".pdf", getActivity().getCacheDir().getPath()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 

PdfPrint類生成PDF。

package com.example.nisarg.invoice; 

import android.os.Bundle; 
import android.os.CancellationSignal; 
import android.os.ParcelFileDescriptor; 
import android.print.PageRange; 
import android.print.PrintAttributes; 
import android.print.PrintDocumentAdapter; 
import android.util.Log; 

import com.example.nisarg.invoice.android.print.ProxyBuilder; 

import java.io.File; 
import java.io.IOException; 
import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Method; 

import static com.example.nisarg.invoice.Database.appglobal.context; 

public class PdfPrint { 

    public static final String TAG = PdfPrint.class.getSimpleName(); 
    public static PrintAttributes printAttributes; 
    File cacheFolder; 


    public PdfPrint(PrintAttributes printAttributes) { 
     this.printAttributes = printAttributes; 
     cacheFolder = new File(context.getFilesDir() + "/etemp/"); 
    } 

    public static PrintDocumentAdapter.WriteResultCallback getWriteResultCallback(InvocationHandler invocationHandler, 
                        File dexCacheDir) throws IOException { 
     return ProxyBuilder.forClass(PrintDocumentAdapter.WriteResultCallback.class) 
       .dexCache(dexCacheDir) 
       .handler(invocationHandler) 
       .build(); 
    } 

    public static PrintDocumentAdapter.LayoutResultCallback getLayoutResultCallback(InvocationHandler invocationHandler, 
                        File dexCacheDir) throws IOException { 
     return ProxyBuilder.forClass(PrintDocumentAdapter.LayoutResultCallback.class) 
       .dexCache(dexCacheDir) 
       .handler(invocationHandler) 
       .build(); 
    } 

    /* public void print(final PrintDocumentAdapter printAdapter, final File path, final String fileName) { 
     printAdapter.onLayout(null, printAttributes, null, new PrintDocumentAdapter.LayoutResultCallback() { 
      @Override 
      public void onLayoutFinished(PrintDocumentInfo info, boolean changed) { 


       try { 
        PrintDocumentAdapter.WriteResultCallback callback = getWriteResultCallback(new InvocationHandler() { 
         @Override 
         public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 
          if (method.getName().equals("onWriteFinished")) { 
           //       pdfCallback.onPdfCreated(); 
          } else { 
           Log.e(TAG, "Layout failed"); 
           //       pdfCallback.onPdfFailed(); 
          } 
          return null; 
         } 
        }, null); 

        printAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(path, fileName), new CancellationSignal(), callback); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 


      } 
     }, null); 
    }*/ 

    public void printNew(final PrintDocumentAdapter printAdapter, final File path, final String fileName, final String fileNamenew) { 

     try { 

      printAdapter.onStart(); 
      printAdapter.onLayout(null, printAttributes, new CancellationSignal(), getLayoutResultCallback(new InvocationHandler() { 
       @Override 
       public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 

        if (method.getName().equals("onLayoutFinished")) { 
         onLayoutSuccess(printAdapter, path, fileName, fileNamenew); 
        } else { 
         Log.e(TAG, "Layout failed"); 

        } 
        return null; 
       } 
      }, new File(fileNamenew)), new Bundle()); 


     } catch (Exception e) { 
      e.printStackTrace(); 

     } 
    } 

    private void onLayoutSuccess(PrintDocumentAdapter printAdapter, File path, String fileName, String filenamenew) throws IOException { 
     PrintDocumentAdapter.WriteResultCallback callback = getWriteResultCallback(new InvocationHandler() { 
      @Override 
      public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 
       if (method.getName().equals("onWriteFinished")) { 

        System.out.print("hello"); 

       } else { 
        Log.e(TAG, "Layout failed"); 

       } 
       return null; 
      } 
     }, new File(filenamenew)); 
     printAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(path, fileName), new CancellationSignal(), callback); 
    } 

    private ParcelFileDescriptor getOutputFile(File path, String fileName) { 
     if (!path.exists()) { 
      path.mkdirs(); 
     } 
     File file = new File(path, fileName); 
     try { 
      file.createNewFile(); 
      return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE); 
     } catch (Exception e) { 
      Log.e(TAG, "Failed to open ParcelFileDescriptor", e); 
     } 
     return null; 
    } 
} 

生成代理類。[https://gist.github.com/brettwold/838c092329c486b6112c8ebe94c8007e]

對於依賴其在代理生成器類使用的gradle中添加此行。

compile 'com.linkedin.dexmaker:dexmaker-mockito:2.2.0'