Skip to content

Commit 5d4092b

Browse files
IslamSalahchristopherdro
authored andcommitted
iText dependency has been removed form android platform. (#51)
* iText dependency has been removed form android platform. * Allow Base64 encoding. Throw exceptions rather than silent failures.
1 parent 5a66f12 commit 5d4092b

File tree

3 files changed

+145
-44
lines changed

3 files changed

+145
-44
lines changed

android/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,4 @@ repositories {
3434

3535
dependencies {
3636
compile 'com.facebook.react:react-native:+'
37-
compile 'com.itextpdf:itextg:5.5.9'
38-
compile 'com.itextpdf.tool:xmlworker:5.5.9'
3937
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Created on 11/15/17.
3+
* Written by Islam Salah with assistance from members of Blink22.com
4+
*/
5+
6+
package android.print;
7+
8+
import android.content.Context;
9+
import android.os.Build;
10+
import android.os.Handler;
11+
import android.os.ParcelFileDescriptor;
12+
import android.util.Log;
13+
import android.webkit.WebView;
14+
import android.webkit.WebViewClient;
15+
16+
import java.io.File;
17+
18+
/**
19+
* Converts HTML to PDF.
20+
* <p>
21+
* Can convert only one task at a time, any requests to do more conversions before
22+
* ending the current task are ignored.
23+
*/
24+
public class PdfConverter implements Runnable {
25+
26+
private static final String TAG = "PdfConverter";
27+
private static PdfConverter sInstance;
28+
29+
private Context mContext;
30+
private String mHtmlString;
31+
private File mPdfFile;
32+
private PrintAttributes mPdfPrintAttrs;
33+
private boolean mIsCurrentlyConverting;
34+
private WebView mWebView;
35+
36+
private PdfConverter() {
37+
}
38+
39+
public static synchronized PdfConverter getInstance() {
40+
if (sInstance == null)
41+
sInstance = new PdfConverter();
42+
43+
return sInstance;
44+
}
45+
46+
@Override
47+
public void run() {
48+
mWebView = new WebView(mContext);
49+
mWebView.setWebViewClient(new WebViewClient() {
50+
@Override
51+
public void onPageFinished(WebView view, String url) {
52+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
53+
throw new RuntimeException("call requires API level 19");
54+
else {
55+
PrintDocumentAdapter documentAdapter = mWebView.createPrintDocumentAdapter();
56+
documentAdapter.onLayout(null, getPdfPrintAttrs(), null, new PrintDocumentAdapter.LayoutResultCallback() {
57+
}, null);
58+
documentAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFileDescriptor(), null, new PrintDocumentAdapter.WriteResultCallback() {
59+
@Override
60+
public void onWriteFinished(PageRange[] pages) {
61+
destroy();
62+
}
63+
});
64+
}
65+
}
66+
});
67+
mWebView.loadData(mHtmlString, "text/HTML", "UTF-8");
68+
}
69+
70+
public PrintAttributes getPdfPrintAttrs() {
71+
return mPdfPrintAttrs != null ? mPdfPrintAttrs : getDefaultPrintAttrs();
72+
}
73+
74+
public void setPdfPrintAttrs(PrintAttributes printAttrs) {
75+
this.mPdfPrintAttrs = printAttrs;
76+
}
77+
78+
public void convert(Context context, String htmlString, File file) {
79+
if (context == null)
80+
throw new IllegalArgumentException("context can't be null");
81+
if (htmlString == null)
82+
throw new IllegalArgumentException("htmlString can't be null");
83+
if (file == null)
84+
throw new IllegalArgumentException("file can't be null");
85+
86+
if (mIsCurrentlyConverting)
87+
return;
88+
89+
mContext = context;
90+
mHtmlString = htmlString;
91+
mPdfFile = file;
92+
mIsCurrentlyConverting = true;
93+
runOnUiThread(this);
94+
}
95+
96+
private ParcelFileDescriptor getOutputFileDescriptor() {
97+
try {
98+
mPdfFile.createNewFile();
99+
return ParcelFileDescriptor.open(mPdfFile, ParcelFileDescriptor.MODE_TRUNCATE | ParcelFileDescriptor.MODE_READ_WRITE);
100+
} catch (Exception e) {
101+
Log.d(TAG, "Failed to open ParcelFileDescriptor", e);
102+
}
103+
return null;
104+
}
105+
106+
private PrintAttributes getDefaultPrintAttrs() {
107+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return null;
108+
109+
return new PrintAttributes.Builder()
110+
.setMediaSize(PrintAttributes.MediaSize.NA_GOVT_LETTER)
111+
.setResolution(new PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
112+
.setMinMargins(PrintAttributes.Margins.NO_MARGINS)
113+
.build();
114+
115+
}
116+
117+
private void runOnUiThread(Runnable runnable) {
118+
Handler handler = new Handler(mContext.getMainLooper());
119+
handler.post(runnable);
120+
}
121+
122+
private void destroy() {
123+
mContext = null;
124+
mHtmlString = null;
125+
mPdfFile = null;
126+
mPdfPrintAttrs = null;
127+
mIsCurrentlyConverting = false;
128+
mWebView = null;
129+
}
130+
}

android/src/main/java/com/christopherdro/htmltopdf/RNHTMLtoPDFModule.java

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,21 @@
77
import com.facebook.react.bridge.ReadableMap;
88
import com.facebook.react.bridge.Promise;
99
import com.facebook.react.bridge.WritableMap;
10-
import com.facebook.react.bridge.ReadableArray;
1110

1211
import java.io.File;
13-
import java.io.FileOutputStream;
14-
import java.io.InputStream;
15-
import java.io.ByteArrayInputStream;
1612
import java.util.UUID;
17-
import java.util.HashSet;
18-
import java.util.Set;
19-
import java.nio.charset.Charset;
2013

21-
import com.itextpdf.text.Document;
22-
import com.itextpdf.text.pdf.PdfWriter;
23-
import com.itextpdf.text.pdf.codec.Base64;
24-
import com.itextpdf.tool.xml.XMLWorkerHelper;
25-
import com.itextpdf.text.FontFactory;
26-
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
14+
import android.util.Base64;
15+
import java.io.IOException;
16+
import java.io.RandomAccessFile;
17+
2718

2819
import android.os.Environment;
20+
import android.print.PdfConverter;
2921

3022
public class RNHTMLtoPDFModule extends ReactContextBaseJavaModule {
3123

32-
private Promise promise;
3324
private final ReactApplicationContext mReactContext;
34-
private Set<String> customFonts = new HashSet<>();
35-
36-
XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
3725

3826
public RNHTMLtoPDFModule(ReactApplicationContext reactContext) {
3927
super(reactContext);
@@ -59,15 +47,6 @@ public void convert(final ReadableMap options, final Promise promise) {
5947
fileName = UUID.randomUUID().toString();
6048
}
6149

62-
if (options.hasKey("fonts")) {
63-
if (options.getArray("fonts") != null) {
64-
final ReadableArray fonts = options.getArray("fonts");
65-
for (int i = 0; i < fonts.size(); i++) {
66-
customFonts.add(fonts.getString(i));
67-
}
68-
}
69-
}
70-
7150
if (options.hasKey("directory") && options.getString("directory").equals("docs")) {
7251
String state = Environment.getExternalStorageState();
7352
File path = (Environment.MEDIA_MOUNTED.equals(state)) ?
@@ -84,9 +63,10 @@ public void convert(final ReadableMap options, final Promise promise) {
8463
String base64 = "";
8564

8665
if (options.hasKey("base64") && options.getBoolean("base64") == true) {
87-
base64 = Base64.encodeFromFile(filePath);
66+
base64 = encodeFromFile(destinationFile);
8867
}
8968

69+
9070
WritableMap resultMap = Arguments.createMap();
9171
resultMap.putString("filePath", filePath);
9272
resultMap.putString("base64", base64);
@@ -99,21 +79,8 @@ public void convert(final ReadableMap options, final Promise promise) {
9979

10080
private String convertToPDF(String htmlString, File file) throws Exception {
10181
try {
102-
Document doc = new Document();
103-
InputStream in = new ByteArrayInputStream(htmlString.getBytes());
104-
105-
PdfWriter pdf = PdfWriter.getInstance(doc, new FileOutputStream(file));
106-
107-
FontFactory.setFontImp(fontProvider);
108-
for (String font : customFonts) {
109-
fontProvider.register( font );
110-
}
111-
112-
doc.open();
113-
XMLWorkerHelper.getInstance().parseXHtml(pdf, doc, in, null, Charset.forName("UTF-8"), fontProvider);
114-
doc.close();
115-
in.close();
116-
82+
PdfConverter.getInstance()
83+
.convert(mReactContext, htmlString, file);
11784
String absolutePath = file.getAbsolutePath();
11885

11986
return absolutePath;
@@ -134,4 +101,10 @@ private File getTempFile(String fileName) throws Exception {
134101
}
135102
}
136103

104+
private String encodeFromFile(File file) throws IOException{
105+
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
106+
byte[] fileBytes = new byte[(int)randomAccessFile.length()];
107+
randomAccessFile.readFully(fileBytes);
108+
return Base64.encodeToString(fileBytes, Base64.DEFAULT);
109+
}
137110
}

0 commit comments

Comments
 (0)