Saving Webview to Pdf Returns Blank Image

Saving WebView to PDF returns blank image?

iOS 11.0 and above, Apple has provided following API to capture snapshot of WKWebView.

@available(iOS 11.0, *)
open func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration?, completionHandler: @escaping (UIImage?, Error?) -> Swift.Void)

Sample usage:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

if #available(iOS 11.0, *) {
webView.takeSnapshot(with: nil) { (image, error) in
//Do your stuff with image
}
}
}

iOS 10 and below, UIWebView has to be used to capture snapshot. Following method can be used to achieve that.

func webViewDidFinishLoad(_ webView: UIWebView) {

let image = captureScreen(webView: webView)
//Do your stuff with image
}

func captureScreen(webView: UIWebView) -> UIImage {
UIGraphicsBeginImageContext(webView.bounds.size)
webView.layer.render(in: UIGraphicsGetCurrentContext()!)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}

Here's another relevant answer

Android Webview, trying to save as image file only seems to store a blank image

As it turns out, the webview isn't rendered until sometime after onPageFinished. All of this code being in my onCreate was saving a blank image because the webview hadn't been rendered yet.

Ended up doing this as a separate method outside onCreate:

    public Bitmap getBitmapFromWebView(View v) {
webView.setDrawingCacheEnabled(true);
webView.buildDrawingCache(true);
Bitmap bitmap = Bitmap.createBitmap(v.getDrawingCache());
try {
FileOutputStream fos = openFileOutput("test.png", Context.MODE_PRIVATE);
//fos = new FileOutputStream( "/sdcard/" + "page.jpg" );
if (fos != null) {
bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.close();
}
} catch (Exception e) {
System.out.println("-----error--" + e);
}
return bitmap;
}

And calling this method from within a "submit" button onclick in the onCreate.

Saving a webview as html and pdf

You got the answer? If not try this one.

    NSData *pdfData = [[[[webview mainFrame] frameView] documentView] dataWithPDFInsideRect:[[[webview mainFrame] frameView] documentView].frame]; 
PDFDocument *document = [[PDFDocument alloc] initWithData:pdfData];
[document writeToFile:@"/Users/MyName/Desktop/test.pdf"];

How to create PDF from webview in android?

Try like this

WebView have inbuilt method called setPictureListener Use that method as below

webView1.setPictureListener(new PictureListener() {

public void onNewPicture(WebView view, Picture picture) {
if (picture != null) {
try {
bmp = pictureDrawable2Bitmap(new PictureDrawable(
picture));

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

For obtaining bitmap i have used pictureDrawable2Bitmap and here is that one

private static Bitmap pictureDrawable2Bitmap(PictureDrawable pictureDrawable) {
Bitmap bitmap = Bitmap.createBitmap(
pictureDrawable.getIntrinsicWidth(),
pictureDrawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawPicture(pictureDrawable.getPicture());
return bitmap;
}

Now Your Bitmap is ready,Now set webview client as below

webView1.setWebViewClient(new myWebClient());

And here is myWebClient

public class myWebClient extends WebViewClient {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// TODO Auto-generated method stub

view.loadUrl(url);
return true;

}

@Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
Log.i("OnPageLoadFinished", url);
img.setImageBitmap(bmp);
}

As shown on page load finished i have set image bitmap which is snap of current loaded url on your webview

Now Bitmap is ready pass that bitmap to Pdf using IText Library

Here is an example of writing pdf with image on iText Use Below function for that

public void SimplePDFTable() throws Exception {

File direct = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/AamirPDF");
if (!direct.exists()) {
if (direct.mkdir()) {
Toast.makeText(MainActivity.this,
"Folder Is created in sd card", Toast.LENGTH_SHORT)
.show();
}
}
String test = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/AamirPDF";
Document document = new Document();

PdfWriter.getInstance(document, new FileOutputStream(test
+ "/mypdf.pdf"));

document.open();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Image image = Image.getInstance(byteArray);


image.scaleToFit(PageSize.A4.getHeight(), PageSize.A4.getWidth());
document.add(image);

document.close();

}

Good Luck

PDF displays empty the first time it's loaded on Android

So there are a couple of ways to handle the flow, but I would go with just an event or an Observable.

So lets convert your WebViewCallBack to something that actually performs a callback when its OnPageFinished is called. This is using System.Reactive but you could also use an EventHandler...

// a few class level variables
bool busy;
WebView webView;
IDisposable WhenPageIsLoadedSubscription;

public class WebViewObservable : WebViewClient
{
Subject<string> pageLoaded = new Subject<string>();

public IObservable<string> WhenPageIsLoaded
{
get { return pageLoaded.AsObservable(); }
}

public override void OnPageFinished(WebView view, string url)
{
pageLoaded.OnNext(url);
}
}

Now define your print routine (the calls in your original OnPageFinished and Print method). This will automatically be called when the webpage is finished loading.

void PrintWebPage(WebView webView, string url)
{
Log.Debug("SO", $"Page: {url} loaded, lets print it now" );

// Perform the work that you used to do in OnPageFinished

// Perform the work in your Print method

// Now turn off a Progress indictor if desired

busy = false;
}

Setup your WebView with the observable that calls the PrintWebPage action every time a page is loaded...

void LoadAndPrintWebPage(string html))
{
busy = true;
if (webView == null)
{
int width = 2100;
int height = 2970;

webView = new WebView(this);
var client = new WebViewObservable();
WhenPageIsLoadedSubscription = client.WhenPageIsLoaded.Subscribe((url) => { PrintWebPage(webView, url); });
webView.SetWebViewClient(client);
webView.Layout(0, 0, width, height);
}
webView.LoadData(html, "text/html", "UTF-8");
}

Now call LoadWebPage with your html content and it will be automatically printed after the page is finished loading...

 LoadAndPrintWebPage(html);

When you are done, clean up your observable and webview to avoid memory leaks...

void CleanupWebView()
{
WhenPageIsLoadedSubscription?.Dispose();
webView?.Dispose();
webView = null;
}

Displaying modified PDF page in PDF View without saving locally

You can create a PDFDocument from Data. Use .dataRepresentation() on your PDFDocument to get the data, and PDFDocument(data: ) to create the PDFDocument from the data.

let data = myPDFDocument.dataRepresentation()
let anotherDocument = PDFDocument(data: data)


Related Topics



Leave a reply



Submit