Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f10e625
Add page options to example
esutton Feb 15, 2018
a542d1b
Add page size and orientation options
Feb 15, 2018
92405b6
Document page options
Feb 15, 2018
ff9a3ee
This close #1
esutton Feb 17, 2018
650bbdb
Add docs for images from Android assets
esutton Feb 17, 2018
06661ed
Add iOS support for page option size and orientation
esutton Feb 18, 2018
a4240b9
Refactor variable name
esutton Feb 18, 2018
543b2bd
Update README.md
esutton Feb 18, 2018
343f92d
Explain 792 x 612 on iOS equals US letter Landscape
esutton Feb 18, 2018
46c9e6f
Update README.md
esutton Feb 18, 2018
ee7bd54
Change default from A4 to US Letter portrait
esutton Feb 18, 2018
05b1682
size defaults to UsLetter
esutton Feb 18, 2018
4efd6a3
define page size constants in index.js
esutton Feb 19, 2018
b3c3517
Parses page options
esutton Feb 19, 2018
0ed1da8
Move parsing to PdfOptions
esutton Feb 19, 2018
da8a018
Rename package RNHTMLtoPDF to RnHtmlToPdf so can maintain RNHTMLtoPDF…
esutton Feb 19, 2018
7a4282a
Expose pageOptions through RNHTMLtoPDF
esutton Feb 19, 2018
710c391
Wrap native call to RnHtmlToPdf.convert in a JS wrapper in index.js
Feb 19, 2018
17d1683
Manually merge inventrix PdfConverter.java async fixes #3
Feb 22, 2018
706ec37
Increment version from 0.5.0 to 0.5.1
esutton Feb 22, 2018
3cdcdc4
Fix async merge issues
Feb 26, 2018
35c8344
0.5.1 to 0.5.2
esutton Feb 26, 2018
96dc8d3
Fix iOS parsing of page size options
Mar 1, 2018
6270cee
Add requiresMainQueueSetup
Mar 1, 2018
c6a2ae8
swap width and height in PageStruct to fix Landscape and Portrait modes
esutton Mar 2, 2018
970a722
Copied current production code
Mar 19, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions README.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ class Example extends Component {
html: '<h1>PDF TEST</h1>',
fileName: 'test',
directory: 'docs',
page: {
size: page.size.UsLetter,
orientation: page.orientation.Landscape,
},
};

let file = await RNHTMLtoPDF.convert(options)
Expand All @@ -92,13 +96,12 @@ class Example extends Component {
| `fileName` | `string` | Random | Custom Filename excluding .pdf extension
| `base64` | boolean | false | return base64 string of pdf file (not recommended)


#### iOS Only

| Param | Type | Default | Note |
|---|---|---|---|
| `height` | number | 612 | Set document height (points)
| `width` | number | 792 | Set document width (points)
| `height` | number | 612 | Set document height points to US Letter, Landscape
| `width` | number | 792 | Set document width points to US Letter, Landscape
| `padding` | number | 10 | Outer padding (points)


Expand All @@ -107,3 +110,18 @@ class Example extends Component {
| Param | Type | Default | Note |
|---|---|---|---|
| `fonts` | Array | | Allow custom fonts `['/fonts/TimesNewRoman.ttf', '/fonts/Verdana.ttf']`

### Options: page

| Param | Type | Default | Note |
|---|---|---|---|
| `orientation` | `string` | Portrait | Landscape, Portrait
| `size` | `string` | UsLetter | A0 - A8, UsGovernmentLetter, UsLetter, UsLegal

## Images

````<img src="https://www.pexels.com/photo/cat-animal-pet-9673/" />````

### Android Assets

````<img src="file:///android_asset/images/clientLogo.png" />````
259 changes: 160 additions & 99 deletions android/src/main/java/android/print/PdfConverter.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <p>
* 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);
}
}
Loading