在WebView问题(Xamarin.ios)中查看PDF

时间:2018-11-03 20:52:08

标签: c# ios webview xamarin.ios

我目前在将本地pdf加载到网络视图时遇到问题。我拥有可以正常工作的代码,当我在iPad模拟器上运行它时,它的工作原理绝对完美。但是,当我尝试在物理iPad设备上运行它时,就会出现问题。当我运行它时,它到达需要显示PDF的地步,将加载Web视图,但是在Web视图中没有显示PDF。

PDF实际上是由应用程序生成的,我将其存储在库文件夹内的目录中。

在WebView中显示PDF的代码:

public void LoadPdfToWebView(string pdfPath)
    {
        //Console.WriteLine("Load request started");

        WebView.LoadRequest(new NSUrlRequest(new NSUrl(pdfPath, false)));
        View.AddSubview(WebView);

        //Console.WriteLine("Load request Finished");
    }

不太确定为什么会这样,希望有人能提供帮助。

3 个答案:

答案 0 :(得分:1)

在Xamarin.IOS中在UIWebView中显示HTML以外的文档类型:

  1. 将文档(例如PDF)添加到Xamarin.iOS项目。将“生成操作”设置为BundleResource。您可以通过右键单击该文件并在打开的菜单中选择“构建动作”来设置文件的构建动作。

  2. 创建一个UIWebView并将其添加到视图中:

    webView = new UIWebView (View.Bounds);
    View.AddSubview(webView);
    
  3. 使用NSUrl和NSUrlRequest类加载文件:

    string fileName = "Loading a Web Page.pdf"; // remember case-sensitive
    string localDocUrl = Path.Combine (NSBundle.MainBundle.BundlePath, fileName);
    webView.LoadRequest(new NSUrlRequest(new NSUrl(localDocUrl, false)));
    webView.ScalesPageToFit = true;
    

您可以参考此官方步骤。如果有问题或其他需求,可以参考this link

如果您无法读取捆绑中的资源,则可以将资源缓存放入沙箱的temp目录中,并尝试使用LoadRequest进行读取。

答案 1 :(得分:0)

可能是通过更改info.plist文件解决的 像这样  NSAppTransportSecurity   NSAllowsArbitraryLoads

我建议您使用此项目

   <key>NSAppTransportSecurity</key>
    <dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>mysupersexywebsite.com</key>
        <dict>
        <key>NSIncludesSubdomains</key>
        <true/>
        <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
        <true/>
        </dict>
        <key>subdomain.mysupersexywebsite.com</key>
        <dict>
        <key>NSIncludesSubdomains</key>
        <true/>
        <key>NSExceptionAllowsInsecureHTTPLoads</key>
        <true/>
        </dict>
    </dict>
</dict>

答案 2 :(得分:0)

我刚刚为一个应用修复了这个问题,并想我会发布解决方案

这是针对 WKWebView 的,这是 Apple 自 2020 年 12 月起的一项要求,但截止日期已暂时延长

Xaml PdfWebView 内容页

<controls:PdfWebView
  Source="{Binding PDFSource}"
  HeightRequest="1000"
  WidthRequest="1000"/>

控制

namespace XForms.Controls
{
    public class PdfWebView : WebView { }
}

VM,只有相关部分

private string _pdfSource;
public string PDFSource
{
      get => _pdfSource;
      set
      {
           if (Device.RuntimePlatform == Device.Android && value.StartsWith("file:") == false)
           {
                value = $"file:///android_asset/pdfjs/web/viewer.html?file=file:///{WebUtility.UrlEncode(value)}";
           }
           SetProperty(ref _pdfSource, value);
      }
}

用于 PdfWebView 的 iOS 渲染器

using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using XForms.Controls;
using WebKit;
using Foundation;

[assembly: ExportRenderer(typeof(PdfWebView), typeof(iOSUI.Renderers.PdfWebViewRenderer))]
namespace iOSUI.Renderers
{
    public class PdfWebViewRenderer : ViewRenderer<WebView, WKWebView>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                var wkWebViewConfiguration = new WKWebViewConfiguration();

                var wkWebView = new WKWebView(Frame, wkWebViewConfiguration)
                {
                    AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
                };
                SetNativeControl(wkWebView);
            }
            if (e.NewElement != null)
            {
                if (string.IsNullOrEmpty(((UrlWebViewSource)e.NewElement.Source)?.Url) == false)
                {
                    var url = ((UrlWebViewSource)e.NewElement.Source).Url;
                    if(url.StartsWith("http"))
                    {
                        Control.LoadRequest(new NSUrlRequest(new NSUrl(url)));
                    }
                    else
                    {
                        Control.LoadFileUrl(new NSUrl($"file://{url}"), new NSUrl($"file://{url}"));
                    }
                }
            }
        }
    }
}

安卓渲染器

using System.Net;
using Android.Content;
using Android.Views;
using Android.Webkit;
using XForms.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(PdfWebView), typeof(AndroidUI.Renderers.PDFViewRenderer))]
namespace AndroidUI.Renderers
{
    public class PDFViewRenderer : WebViewRenderer
    {
        public PDFViewRenderer(Context context) : base(context) { }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement != null)
            {
                Control.Settings.JavaScriptEnabled = true;
                Control.Settings.DomStorageEnabled = true;
                Control.Settings.AllowFileAccess = true;
                Control.Settings.AllowFileAccessFromFileURLs = true;
                Control.Settings.AllowUniversalAccessFromFileURLs = true;

                Control.SetWebChromeClient(new WebChromeClient());
            }
        }

        // If you want to enable scrolling in WebView uncomment the following lines.
        public override bool DispatchTouchEvent(MotionEvent e)
        {
            Parent.RequestDisallowInterceptTouchEvent(true);
            return base.DispatchTouchEvent(e);
        }
    }
}

此解决方案使用 Android 中的 pdfjs 和 iOS 中的 WKWebview 来呈现 PDF

PDFSource 是文件的完整路径,我使用 System.IO .net 标准调用以跨平台方式处理此问题

所有文件都存放在(我有个方法叫GetFullPath,返回跨平台通用路径)

Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)

结合文件名和 Path.Combine

Path.Combine(GetFullPath(), fileName);

这是在 VM 中设置的 PDFSource

Pdfjs 库文件只是复制到 Assets/pdfjs for Android 中

iOS 的神奇之处在于调用 LoadFileUrl 而不是 LoadRequest 并在前面加上“file://”

我稍微清理了我们的命名空间,因此其中一些不会像 XForms.Controls 等那样解析我们的内部代码