diff --git a/README.md b/README.md old mode 100644 new mode 100755 index cbc5e5b..67aa58c --- a/README.md +++ b/README.md @@ -68,6 +68,10 @@ class Example extends Component { html: '
````
diff --git a/android/src/main/java/android/print/PdfConverter.java b/android/src/main/java/android/print/PdfConverter.java
old mode 100644
new mode 100755
index 44d9a2f..43d5253
--- a/android/src/main/java/android/print/PdfConverter.java
+++ b/android/src/main/java/android/print/PdfConverter.java
@@ -14,117 +14,178 @@
import android.webkit.WebViewClient;
import java.io.File;
+import android.util.Base64;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import com.facebook.react.bridge.Promise;
+import com.facebook.react.bridge.ReadableMap;
+import com.facebook.react.bridge.WritableMap;
/**
* Converts HTML to PDF.
*
- * Can convert only one task at a time, any requests to do more conversions before
- * ending the current task are ignored.
+ * Can convert only one task at a time, any requests to do more conversions
+ * before ending the current task are ignored.
*/
public class PdfConverter implements Runnable {
- private static final String TAG = "PdfConverter";
- private static PdfConverter sInstance;
-
- private Context mContext;
- private String mHtmlString;
- private File mPdfFile;
- private PrintAttributes mPdfPrintAttrs;
- private boolean mIsCurrentlyConverting;
- private WebView mWebView;
+ private static final String TAG = "PdfConverter";
+ private static PdfConverter sInstance;
- private PdfConverter() {
- }
+ private Context mContext;
+ private String mHtmlString;
+ private File mPdfFile;
+ private PrintAttributes mPdfPrintAttrs;
+ private boolean mIsCurrentlyConverting;
+ private WebView mWebView;
+ private boolean mShouldEncode;
+ private WritableMap mResultMap;
+ private Promise mPromise;
- public static synchronized PdfConverter getInstance() {
- if (sInstance == null)
- sInstance = new PdfConverter();
+ private PdfConverter() {}
- return sInstance;
+ public static synchronized PdfConverter getInstance() {
+ if (sInstance == null) {
+ sInstance = new PdfConverter();
}
-
- @Override
- public void run() {
- mWebView = new WebView(mContext);
- mWebView.setWebViewClient(new WebViewClient() {
- @Override
- public void onPageFinished(WebView view, String url) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
- throw new RuntimeException("call requires API level 19");
- else {
- PrintDocumentAdapter documentAdapter = mWebView.createPrintDocumentAdapter();
- documentAdapter.onLayout(null, getPdfPrintAttrs(), null, new PrintDocumentAdapter.LayoutResultCallback() {
- }, null);
- documentAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFileDescriptor(), null, new PrintDocumentAdapter.WriteResultCallback() {
- @Override
- public void onWriteFinished(PageRange[] pages) {
- destroy();
- }
- });
+ return sInstance;
+ }
+
+ @Override
+ public void run() {
+ mWebView = new WebView(mContext);
+ mWebView.setWebViewClient(new WebViewClient() {
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
+ throw new RuntimeException("call requires API level 19");
+ else {
+ PrintDocumentAdapter documentAdapter =
+ mWebView.createPrintDocumentAdapter();
+ documentAdapter.onLayout(
+ null, getPdfPrintAttrs(), null,
+ new PrintDocumentAdapter.LayoutResultCallback() {}, null);
+ documentAdapter.onWrite(
+ new PageRange[] {PageRange.ALL_PAGES}, getOutputFileDescriptor(),
+ null, new PrintDocumentAdapter.WriteResultCallback() {
+ @Override
+ public void onWriteFinished(PageRange[] pages) {
+ try {
+ String base64 = "";
+ if (mShouldEncode) {
+ base64 = encodeFromFile(mPdfFile);
+ }
+ mResultMap.putString("filePath",
+ mPdfFile.getAbsolutePath());
+ mResultMap.putString("base64", base64);
+ mPromise.resolve(mResultMap);
+ } catch (IOException e) {
+ mPromise.reject(e.getMessage());
+ } finally {
+ destroy();
+ }
}
- }
- });
- mWebView.loadData(mHtmlString, "text/HTML", "UTF-8");
- }
-
- public PrintAttributes getPdfPrintAttrs() {
- return mPdfPrintAttrs != null ? mPdfPrintAttrs : getDefaultPrintAttrs();
- }
-
- public void setPdfPrintAttrs(PrintAttributes printAttrs) {
- this.mPdfPrintAttrs = printAttrs;
- }
-
- public void convert(Context context, String htmlString, File file) {
- if (context == null)
- throw new IllegalArgumentException("context can't be null");
- if (htmlString == null)
- throw new IllegalArgumentException("htmlString can't be null");
- if (file == null)
- throw new IllegalArgumentException("file can't be null");
-
- if (mIsCurrentlyConverting)
- return;
-
- mContext = context;
- mHtmlString = htmlString;
- mPdfFile = file;
- mIsCurrentlyConverting = true;
- runOnUiThread(this);
- }
-
- private ParcelFileDescriptor getOutputFileDescriptor() {
- try {
- mPdfFile.createNewFile();
- return ParcelFileDescriptor.open(mPdfFile, ParcelFileDescriptor.MODE_TRUNCATE | ParcelFileDescriptor.MODE_READ_WRITE);
- } catch (Exception e) {
- Log.d(TAG, "Failed to open ParcelFileDescriptor", e);
+ });
}
- return null;
- }
-
- private PrintAttributes getDefaultPrintAttrs() {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return null;
-
- return new PrintAttributes.Builder()
- .setMediaSize(PrintAttributes.MediaSize.NA_GOVT_LETTER)
- .setResolution(new PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
- .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
- .build();
-
- }
-
- private void runOnUiThread(Runnable runnable) {
- Handler handler = new Handler(mContext.getMainLooper());
- handler.post(runnable);
- }
-
- private void destroy() {
- mContext = null;
- mHtmlString = null;
- mPdfFile = null;
- mPdfPrintAttrs = null;
- mIsCurrentlyConverting = false;
- mWebView = null;
+ }
+ });
+ mWebView.loadDataWithBaseURL(null, mHtmlString, "text/html", "utf-8", null);
+ }
+
+ public PrintAttributes getPdfPrintAttrs() {
+ return mPdfPrintAttrs != null ? mPdfPrintAttrs : getDefaultPrintAttrs();
+ }
+
+ public void setPdfPrintAttrs(PrintAttributes printAttrs) {
+ this.mPdfPrintAttrs = printAttrs;
+ }
+
+ public void convert(Context context, String htmlString, File file,
+ final ReadableMap options, WritableMap resultMap,
+ Promise promise) {
+ if (context == null)
+ throw new IllegalArgumentException("context can't be null");
+ if (htmlString == null)
+ throw new IllegalArgumentException("htmlString can't be null");
+ if (file == null)
+ throw new IllegalArgumentException("file can't be null");
+
+ if (mIsCurrentlyConverting)
+ return;
+
+ PdfOptions pdfOptions = new PdfOptions(options);
+ Log.d(TAG, pdfOptions.toString());
+ setOptions(pdfOptions);
+
+ mContext = context;
+ mHtmlString = htmlString;
+ mPdfFile = file;
+ mIsCurrentlyConverting = true;
+ mShouldEncode = pdfOptions.getShouldEncode();
+ mResultMap = resultMap;
+ mPromise = promise;
+ runOnUiThread(this);
+ }
+
+ private ParcelFileDescriptor getOutputFileDescriptor() {
+ try {
+ mPdfFile.createNewFile();
+ return ParcelFileDescriptor.open(
+ mPdfFile, ParcelFileDescriptor.MODE_TRUNCATE |
+ ParcelFileDescriptor.MODE_READ_WRITE);
+ } catch (Exception e) {
+ Log.d(TAG, "Failed to open ParcelFileDescriptor", e);
}
+ return null;
+ }
+
+ private PrintAttributes getDefaultPrintAttrs() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
+ return null;
+
+ return new PrintAttributes.Builder()
+ .setMediaSize(PrintAttributes.MediaSize.NA_GOVT_LETTER)
+ .setResolution(new PrintAttributes.Resolution(
+ "RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
+ .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
+ .build();
+ }
+
+ private void setOptions(final PdfOptions pdfOptions) {
+ PrintAttributes.MediaSize mediaSize = pdfOptions.getMediaSize();
+ PrintAttributes printAttributes =
+ new PrintAttributes.Builder()
+ .setMediaSize(mediaSize)
+ .setResolution(new PrintAttributes.Resolution(
+ "RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
+ .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
+ .build();
+
+ setPdfPrintAttrs(printAttributes);
+ }
+
+ private void runOnUiThread(Runnable runnable) {
+ Handler handler = new Handler(mContext.getMainLooper());
+ handler.post(runnable);
+ }
+
+ private void destroy() {
+ mContext = null;
+ mHtmlString = null;
+ mPdfFile = null;
+ mPdfPrintAttrs = null;
+ mIsCurrentlyConverting = false;
+ mWebView = null;
+ mShouldEncode = false;
+ mResultMap = null;
+ mPromise = null;
+ }
+
+ private String encodeFromFile(File file) throws IOException {
+ RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
+ byte[] fileBytes = new byte[(int)randomAccessFile.length()];
+ randomAccessFile.readFully(fileBytes);
+ return Base64.encodeToString(fileBytes, Base64.DEFAULT);
+ }
}
diff --git a/android/src/main/java/android/print/PdfOptions.java b/android/src/main/java/android/print/PdfOptions.java
new file mode 100755
index 0000000..b340589
--- /dev/null
+++ b/android/src/main/java/android/print/PdfOptions.java
@@ -0,0 +1,156 @@
+/*
+ *
+ * Ed Sutton
+ */
+
+package android.print;
+
+import com.facebook.react.bridge.ReadableMap;
+
+import android.content.Context;
+import android.os.Build;
+import android.os.Handler;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import java.io.File;
+
+/**
+ * Parses page options
+ */
+public class PdfOptions {
+
+ private static final String TAG = "PdfOptions";
+
+ private static final String OrientationLandscape = "Landscape";
+
+ private static final double MillimetersToInches = 0.0393701;
+ private static final double MillimetersToPoints = 2.83465;
+
+ private static String _pageOrientation = "Portrait";
+ private static String _pageId = "";
+ private static double _pageHeightMm = 0;
+ private static double _pageWidthMm = 0;
+ private static boolean _shouldEncode = false;
+
+ // Missing option default values should have been added by JS
+ public PdfOptions(final ReadableMap options) {
+ _shouldEncode = options.hasKey("base64") ? options.getBoolean("base64") : _shouldEncode;
+
+ if (!options.hasKey("page")) {
+ throw new IllegalArgumentException("option not found: page");
+ }
+ final ReadableMap page = options.getMap("page");
+ _pageOrientation = page.hasKey("orientation") ? page.getString("orientation") : _pageOrientation;
+ if (!page.hasKey("size")) {
+ throw new IllegalArgumentException("option not found: page.size");
+ }
+ final ReadableMap pageSize = page.getMap("size");
+ _pageId = pageSize.hasKey("id") ? pageSize.getString("id") : _pageId;
+ if (!pageSize.hasKey("mm")) {
+ throw new IllegalArgumentException("option not found: page.size.mm");
+ }
+ final ReadableMap pageSizeMm = pageSize.getMap("mm");
+ _pageHeightMm = pageSizeMm.hasKey("h") ? pageSizeMm.getDouble("h") : _pageHeightMm;
+ _pageWidthMm = pageSizeMm.hasKey("w") ? pageSizeMm.getDouble("w") : _pageWidthMm;
+ }
+
+ public String getPageOrientation() {
+ return _pageOrientation;
+ }
+
+ // "A4", "UsLetter", etc
+ public String getPageId() {
+ return _pageId;
+ }
+
+ public double getPageHeightMm() {
+ return _pageHeightMm;
+ }
+
+ public double getPageWidthMm() {
+ return _pageWidthMm;
+ }
+
+ public boolean getShouldEncode() {
+ return _shouldEncode;
+ }
+
+
+
+ public String toString() {
+ return String.format("%s Page: %s, %f inch x %f inch ( %f pt x %f pt ) ( %f mm x %f mm )",
+ _pageOrientation,
+ _pageId,
+ _pageWidthMm * MillimetersToInches,
+ _pageHeightMm * MillimetersToInches,
+ _pageWidthMm * MillimetersToPoints,
+ _pageHeightMm * MillimetersToPoints,
+ _pageWidthMm,
+ _pageHeightMm);
+ }
+
+ // How to create a PrintAttributes.MediaSize from page data w x h declared in JS?
+ // This switch statement smells like it will be hard to maintain
+ public static PrintAttributes.MediaSize getMediaSize(String pageId,
+ String orientation) {
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ throw new RuntimeException("call requires API level 19");
+ }
+
+ PrintAttributes.MediaSize mediaSize = null;
+ switch (pageId) {
+ case "A0":
+ mediaSize = PrintAttributes.MediaSize.ISO_A0;
+ break;
+ case "A1":
+ mediaSize = PrintAttributes.MediaSize.ISO_A1;
+ break;
+ case "A2":
+ mediaSize = PrintAttributes.MediaSize.ISO_A2;
+ break;
+ case "A3":
+ mediaSize = PrintAttributes.MediaSize.ISO_A3;
+ break;
+ case "A4":
+ mediaSize = PrintAttributes.MediaSize.ISO_A4;
+ break;
+ case "A5":
+ mediaSize = PrintAttributes.MediaSize.ISO_A5;
+ break;
+ case "A6":
+ mediaSize = PrintAttributes.MediaSize.ISO_A6;
+ break;
+ case "A7":
+ mediaSize = PrintAttributes.MediaSize.ISO_A7;
+ break;
+ case "A8":
+ mediaSize = PrintAttributes.MediaSize.ISO_A8;
+ break;
+ case "UsGovernmentLetter":
+ mediaSize = PrintAttributes.MediaSize.NA_GOVT_LETTER;
+ break;
+ case "UsLetter":
+ mediaSize = PrintAttributes.MediaSize.NA_LETTER;
+ break;
+ case "UsLegal":
+ mediaSize = PrintAttributes.MediaSize.NA_LEGAL;
+ break;
+ default:
+ mediaSize = PrintAttributes.MediaSize.ISO_A4;
+ break;
+ }
+ if (orientation.equalsIgnoreCase(OrientationLandscape)) {
+ return mediaSize.asLandscape();
+ }
+ return mediaSize;
+ }
+
+ public PrintAttributes.MediaSize getMediaSize() {
+ return getMediaSize(_pageId, _pageOrientation);
+ }
+
+}
diff --git a/android/src/main/java/com/christopherdro/htmltopdf/RNHTMLtoPDFModule.java b/android/src/main/java/com/christopherdro/htmltopdf/RNHTMLtoPDFModule.java
old mode 100644
new mode 100755
index 0596955..d99c0dd
--- a/android/src/main/java/com/christopherdro/htmltopdf/RNHTMLtoPDFModule.java
+++ b/android/src/main/java/com/christopherdro/htmltopdf/RNHTMLtoPDFModule.java
@@ -23,6 +23,8 @@ public class RNHTMLtoPDFModule extends ReactContextBaseJavaModule {
private final ReactApplicationContext mReactContext;
+ private ReadableMap mIntializerList;
+
public RNHTMLtoPDFModule(ReactApplicationContext reactContext) {
super(reactContext);
mReactContext = reactContext;
@@ -30,9 +32,11 @@ public RNHTMLtoPDFModule(ReactApplicationContext reactContext) {
@Override
public String getName() {
- return "RNHTMLtoPDF";
+ //return "RNHTMLtoPDF";
+ return "RnHtmlToPdf";
}
+
@ReactMethod
public void convert(final ReadableMap options, final Promise promise) {
try {
@@ -59,30 +63,29 @@ public void convert(final ReadableMap options, final Promise promise) {
destinationFile = getTempFile(fileName);
}
- String filePath = convertToPDF(htmlString, destinationFile);
- String base64 = "";
-
- if (options.hasKey("base64") && options.getBoolean("base64") == true) {
- base64 = encodeFromFile(destinationFile);
- }
-
-
- WritableMap resultMap = Arguments.createMap();
- resultMap.putString("filePath", filePath);
- resultMap.putString("base64", base64);
-
- promise.resolve(resultMap);
+ convertToPDF(
+ htmlString,
+ destinationFile,
+ options,
+ Arguments.createMap(),
+ promise
+ );
} catch (Exception e) {
promise.reject(e.getMessage());
}
}
- private String convertToPDF(String htmlString, File file) throws Exception {
+ private String convertToPDF(String htmlString, File file, ReadableMap options, WritableMap resultMap, Promise promise) throws Exception {
try {
- PdfConverter.getInstance()
- .convert(mReactContext, htmlString, file);
+ PdfConverter pdfConverter = PdfConverter.getInstance();
+ pdfConverter.convert(
+ mReactContext,
+ htmlString,
+ file,
+ options,
+ resultMap,
+ promise);
String absolutePath = file.getAbsolutePath();
-
return absolutePath;
} catch (Exception e) {
throw new Exception(e);
@@ -101,10 +104,4 @@ private File getTempFile(String fileName) throws Exception {
}
}
- private String encodeFromFile(File file) throws IOException{
- RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
- byte[] fileBytes = new byte[(int)randomAccessFile.length()];
- randomAccessFile.readFully(fileBytes);
- return Base64.encodeToString(fileBytes, Base64.DEFAULT);
- }
}
diff --git a/android/src/main/java/com/christopherdro/htmltopdf/RNHTMLtoPDFPackage.java b/android/src/main/java/com/christopherdro/htmltopdf/RNHTMLtoPDFPackage.java
old mode 100644
new mode 100755
diff --git a/index.js b/index.js
old mode 100644
new mode 100755
index 70e9b6e..bf4d12f
--- a/index.js
+++ b/index.js
@@ -1,3 +1,65 @@
import { NativeModules } from 'react-native';
-export default NativeModules.RNHTMLtoPDF;
+const { RnHtmlToPdf } = NativeModules;
+
+const pageOptions = {
+ orientation: {
+ Landscape: 'Landscape',
+ Portrait: 'Portrait',
+ },
+
+ // Define page size constants in mm : w x h
+ //
+ // https://developer.android.com/reference/android/print/PrintAttributes.MediaSize.html
+ //
+ // Android uses mm, iOS page size units are points
+ // 1 mm = 2.834646 point; 1 point = 0.352778 mm
+ size: {
+ A0: { id: 'A0', mm: { w: 841, h: 1189 }},
+ A1: { id: 'A1', mm: { w: 594, h: 841 }},
+ A2: { id: 'A2', mm: { w: 420, h: 594 }},
+ A3: { id: 'A3', mm: { w: 297, h: 420 }},
+ A4: { id: 'A4', mm: { w: 210, h: 297 }},
+ A5: { id: 'A5', mm: { w: 148, h: 210 }},
+ A6: { id: 'A6', mm: { w: 105, h: 148 }},
+ A7: { id: 'A7', mm: { w: 74, h: 105 }},
+ A8: { id: 'A8', mm: { w: 52, h: 74 }},
+ UsGovernmentLetter: { id: 'UsGovernmentLetter', mm: { w: 203.2, h: 266.7 }},
+ UsLetter: { id: 'UsLetter', mm: { w: 215.9, h: 279.4 }},
+ UsLegal: { id: 'UsLegal', mm: { w: 279.4, h: 355.6 }},
+ },
+};
+
+// Initialize defaults in JS to reduce maintenance in native modules
+const pdfOptionsDefault = {
+ page: {
+ orientation: pageOptions.orientation.Portrait,
+ size: pageOptions.size.UsLetter,
+ },
+};
+
+const RNHTMLtoPDF = {
+ page: pageOptions,
+
+ async convert(options) {
+ // Create default options if user did not specify
+ if(!options.page) {
+ options.page = pdfOptionsDefault.page;
+ }
+ if(!options.page.size) {
+ options.page.size = pdfOptionsDefault.page.size;
+ }
+ if(!options.page.orientation) {
+ options.page.orientation = pdfOptionsDefault.orientation;
+ }
+ const result = await RnHtmlToPdf.convert(options);
+ return result;
+ },
+
+};
+
+module.exports = {
+ RNHTMLtoPDF,
+}
+
+
diff --git a/ios/RNHTMLtoPDF/PdfOptions.h b/ios/RNHTMLtoPDF/PdfOptions.h
new file mode 100755
index 0000000..38e17c1
--- /dev/null
+++ b/ios/RNHTMLtoPDF/PdfOptions.h
@@ -0,0 +1,20 @@
+
+
+@interface PdfOptions : NSObject {
+
+NSString *pageOrientation;
+NSString *pageId;
+double pageSizeHeightMm;
+double pageSizeWidthMm;
+
+}
+
+-(id)initWithOptions:(NSDictionary *)options;
+- (CGSize) getMediaSize;
+
+@property NSString *pageOrientation;
+@property NSString *pageId;
+@property double pageSizeHeightMm;
+@property double pageSizeWidthMm;
+
+@end
\ No newline at end of file
diff --git a/ios/RNHTMLtoPDF/PdfOptions.m b/ios/RNHTMLtoPDF/PdfOptions.m
new file mode 100755
index 0000000..f1455df
--- /dev/null
+++ b/ios/RNHTMLtoPDF/PdfOptions.m
@@ -0,0 +1,55 @@
+#import