从 UIWebView 或 UIView 获取 PDF/PNG 作为输出

Posted

技术标签:

【中文标题】从 UIWebView 或 UIView 获取 PDF/PNG 作为输出【英文标题】:Get a PDF/PNG as output from a UIWebView or UIView 【发布时间】:2011-01-28 02:23:04 【问题描述】:

有没有办法获取UIWebView 的内容并将其转换为PDF 或PNG 文件?例如,我想通过在从 Safari 打印时选择 PDF 按钮来获得与 Mac 上可用的输出类似的输出。我假设这是不可能的/内置的,但希望我会感到惊讶并找到一种将内容从 web 视图获取到文件的方法。

谢谢!

【问题讨论】:

【参考方案1】:

您可以在 UIView 上使用以下类别来创建 PDF 文件:

#import <QuartzCore/QuartzCore.h>

@implementation UIView(PDFWritingAdditions)

- (void)renderInPDFFile:(NSString*)path

    CGRect mediaBox = self.bounds;
    CGContextRef ctx = CGPDFContextCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path], &mediaBox, NULL);

    CGPDFContextBeginPage(ctx, NULL);
    CGContextScaleCTM(ctx, 1, -1);
    CGContextTranslateCTM(ctx, 0, -mediaBox.size.height);
    [self.layer renderInContext:ctx];
    CGPDFContextEndPage(ctx);
    CFRelease(ctx);


@end

坏消息:UIWebView 不会在 PDF 中创建漂亮的形状和文本,而是将自身呈现为 PDF 中的图像。

【讨论】:

感谢您的帖子。尽管 CGPDFContextCreateWithURL 没有正确创建上下文,但我遇到了一个问题。我尝试了几个不同的网址,但似乎没有任何改变。有什么想法吗? CFURLRef 的创建方式存在错误。我修复了它,它现在应该适用于正确的文件 URL。 使用这种方法渲染 UILabel 似乎会光栅化文本。如果您希望文本保持矢量化,请按照此处***.com/questions/2209734/add-text-to-calayer 中的说明将它们直接绘制到图层中 谁能告诉我如何访问在我的 viewController 中定义的这个方法?因为类别对我来说是全新的 @NikolaiRuhe 如果我们想渲染 UIWebView 内的内容,由于内容不适合框架内,该内容是可滚动的,上面描述的这个答案只渲染 UIWebView 框架内可见的内容。我尝试为 CGRect mediaBox = large hypothetical frame; 提供一个大的假设框架;但结果仍然相同。只有 webView 框架中可见的内容才会在 pdf 中呈现。有什么方法可以在 pdf 中呈现整个 webView 内容(即使是不可见但加载到 webview 中的任何内容)?【参考方案2】:

从 Web 视图创建图像很简单:

UIImage* image = nil;

UIGraphicsBeginImageContext(offscreenWebView_.frame.size);

    [offscreenWebView_.layer renderInContext: UIGraphicsGetCurrentContext()];
    image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

获得图像后,您可以将其保存为 PNG。

也可以以非常相似的方式创建 PDF,但仅限于尚未发布的 iPhone OS 版本。

【讨论】:

我认为 CGPDF... API 从 iPhone OS 2.0 开始就存在了。 是的,但我认为将图层渲染到 PDF 上下文中是新事物。 这个答案几乎也有效。问题是页面之间的页面大小变化。有什么方法可以确定 webview 中内容的大小,以便我可以创建正确大小的上下文? @St3fan 如果我们想在 UIWebView 内渲染内容,由于内容不适合框架内,该内容是可滚动的,上面描述的这个答案只渲染 UIWebView 框架内可见的内容。我尝试为 CGRect mediaBox = large hypothetical frame; 提供一个大的假设框架;但结果仍然相同。只有 webView 框架中可见的内容才会在 pdf 中呈现。有什么方法可以在 pdf 中呈现整个 webView 内容(即使是不可见但加载到 webview 中的任何内容)? @mjdth 如果我们想在 UIWebView 内渲染内容,由于内容不适合框架内的内容而可滚动,那么上面描述的这个答案只会渲染 UIWebView 框架内可见的内容。我尝试为 CGRect mediaBox = large hypothetical frame; 提供一个大的假设框架;但结果仍然相同。只有 webView 框架中可见的内容才会在 pdf 中呈现。有什么方法可以在 pdf 中呈现整个 webView 内容(即使是不可见但加载到 webview 中的任何内容)?【参考方案3】:

@mjdth,试试fileURLWithPath:isDirectory:URLWithString 也不适合我。

@implementation UIView(PDFWritingAdditions)

- (void)renderInPDFFile:(NSString*)path

    CGRect mediaBox = self.bounds;
    CGContextRef ctx = CGPDFContextCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path isDirectory:NO], &mediaBox, NULL);

    CGPDFContextBeginPage(ctx, NULL);
    CGContextScaleCTM(ctx, 1, -1);
    CGContextTranslateCTM(ctx, 0, -mediaBox.size.height);
    [self.layer renderInContext:ctx];
    CGPDFContextEndPage(ctx);
    CFRelease(ctx);


@end

【讨论】:

【参考方案4】:

下面的代码会将 UIWebView 的(完整)内容转换为 UIImage。

渲染 UIImage 后,我将其以 PNG 格式写入磁盘以查看结果。 当然,你可以随心所欲地使用 UIImage。

UIImage *image = nil;
CGRect oldFrame = webView.frame;

// Resize the UIWebView, contentSize could be > visible size
[webView sizeToFit];
CGSize fullSize = webView.scrollView.contentSize;

// Render the layer content onto the image  
UIGraphicsBeginImageContext(fullSize);
CGContextRef resizedContext = UIGraphicsGetCurrentContext();
[webView.layer renderInContext:resizedContext];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

// Revert the UIWebView back to its old size
webView.frame = oldFrame;

// Write the UIImage to disk as PNG so that we can see the result
NSString *path= [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Test.png"];
[UIImagePNGRepresentation(image) writeToFile:path atomically:YES];

注意:确保 UIWebView 已完全加载(UIWebViewDelegate 或 loading 属性)。

【讨论】:

以上是关于从 UIWebView 或 UIView 获取 PDF/PNG 作为输出的主要内容,如果未能解决你的问题,请参考以下文章

将触摸事件从覆盖 UIView 转发到 UIWebView / 如何从代码将触摸事件发送到 uiwebview

将触摸事件从 uiview 传输到 uiwebview

当视频在 UIWebView 中开始或停止时获取通知

如何从 UIWebView 获取内容?

从后台获取加载 UIWebView

在具有动态高度的视图末尾添加一个 UIButton