PdfTextExtractor throws NullReferenceException using iText7 in UWP - c#

Please, notice that this problem can only be reproduced with Visual Studio 2017 Preview. Otherwise, you won't be able to use iText7.
I'm posting this because it's very likely that the problem will remain when the final version comes out.
You can reproduce the issue following these steps:
Create a new Universal Windows project targeting Windows 10 Insider Preview (build
16278), also as the minimum version.
Add the package iText7, version 7.0.4-netstandard
Add one sample PDF file to the root of the project with Buid Action=Content and named "doc.pdf". It can be any PDF. I'm using this one: sample PDF.
Add this code to the MainPage.xaml.cs (code-behind)
MainPage.xaml.cs:
using System;
using System.IO;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas.Parser;
namespace App1
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
using (var stream = await GetStream("doc.pdf"))
{
var pdf = new PdfDocument(new PdfReader(stream));
var text = PdfTextExtractor.GetTextFromPage(pdf.GetPage(1));
}
}
private async Task<Stream> GetStream(string filename)
{
var uri = new Uri(new Uri("ms-appx:///"), filename);
var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
return await file.OpenStreamForReadAsync();
}
}
}
Run the project
It will throw the NullReferenceException like this:
at iText.Kernel.Font.DocType1Font.CreateFontProgram(PdfDictionary
fontDictionary, FontEncoding fontEncoding, CMapToUnicode toUnicode)
at iText.Kernel.Font.PdfType1Font..ctor(PdfDictionary fontDictionary)
at iText.Kernel.Font.PdfFontFactory.CreateFont(PdfDictionary
fontDictionary) at
iText.Kernel.Pdf.Canvas.Parser.PdfCanvasProcessor.GetFont(PdfDictionary
fontDict) at
iText.Kernel.Pdf.Canvas.Parser.PdfCanvasProcessor.SetTextFontOperator.Invoke(PdfCanvasProcessor
processor, PdfLiteral operator, IList1 operands) at
iText.Kernel.Pdf.Canvas.Parser.PdfCanvasProcessor.InvokeOperator(PdfLiteral
operator, IList1 operands) at
iText.Kernel.Pdf.Canvas.Parser.PdfCanvasProcessor.ProcessContent(Byte[]
contentBytes, PdfResources resources) at
iText.Kernel.Pdf.Canvas.Parser.PdfCanvasProcessor.ProcessPageContent(PdfPage
page) at
iText.Kernel.Pdf.Canvas.Parser.PdfTextExtractor.GetTextFromPage(PdfPage
page, ITextExtractionStrategy strategy, IDictionary`2
additionalContentOperators) at
iText.Kernel.Pdf.Canvas.Parser.PdfTextExtractor.GetTextFromPage(PdfPage
page) at App1.MainPage.d__1.MoveNext()

Related

Showing local pdf files from documents folder in xamarin ios webview [duplicate]

Im currently having an issue loading a local pdf into a webview. I have the code which works without any errors and when I run it on the iPad simulator, it works absolutely perfect. However, the issue comes when I try to run it on a physical iPad device. When I run it and it gets to the point where it needs to show the PDF, the webview loads but there is no PDF shown in the webview.
The PDF is actually generated by the app and I store it inside a directory inside the library folder.
Code to show the PDF in the WebView:
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");
}
Not really sure why this would be the case and hopefully somebody can help.
I've just had to fix this for an app and thought I'd post the solution
This is for WKWebView which is a requirement from Apple as of Dec 2020 though the deadline has been temporarily extended
Xaml PdfWebView ContentPage
<controls:PdfWebView
Source="{Binding PDFSource}"
HeightRequest="1000"
WidthRequest="1000"/>
control
namespace XForms.Controls
{
public class PdfWebView : WebView { }
}
VM, only the relevant part
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);
}
}
iOS renderer for PdfWebView
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}"));
}
}
}
}
}
}
Android Renderer
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);
}
}
}
This solution uses pdfjs in Android and WKWebview in iOS to render the PDF
The PDFSource is the full path to the file, I use System.IO .net standard calls to handle this in a cross platform way
All the files are stored in (I have a method called GetFullPath to return the cross platform common path)
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
Combined with a filename with Path.Combine
Path.Combine(GetFullPath(), fileName);
That is the PDFSource that gets set in the VM
The Pdfjs library files are just copied into Assets/pdfjs for Android
The magic for iOS is just calling LoadFileUrl instead of LoadRequest and prepending "file://"
I've slightly sanitised our namespaces so some of them wont resolve like XForms.Controls and so on that refer to our internal code
In Xamarin.IOS to show a document type other than HTML in a UIWebView:
Add the document (for example, a PDF) to your Xamarin.iOS project. Set the Build Action to BundleResource. You can set the build action for a file by right-clicking on that file and and choosing Build Action in the menu that opens.
Create a UIWebView and add it to a view:
webView = new UIWebView (View.Bounds);
View.AddSubview(webView);
Load the file using NSUrl and NSUrlRequest classes:
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;
You can refer to this officical steps.If have problems or other needs, you can refer to this link
If you can't read the resources in the bundle, you can put the resource cache in the temp directory of the sandbox and try to read it using LoadRequest.

UWP SharpCompress Access Exception On Local Drives, Why?

I'm trying to use SharpCompress to read .rar files from my UWP application. It works fine on network shares from which I can read the archive no problem, but I get System.UnauthorizedAccessException on files anywhere on the local system including for instance USB drives. I have access to the files by other methods e.g. StorageFile. It makes no difference whether BroadFileSystemAccess is on or off. I've tried in both C# and Vb.net Here's the code of my test app in C#. The exception occurs at ArchiveFactory.Open.
I can also read Zip files no problem using the .net Compression methods but they can't do rar files, hence needing SharpCompress.
using System;
using System.IO;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using SharpCompress;
using Windows.Storage.Pickers;
using Windows.Storage;
using SharpCompress.Archives;
namespace TestRAR
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
OpenRAR.Click += OpenRAR_Clicked;
}
public async void OpenRAR_Clicked(object sender, RoutedEventArgs e)
{
FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".rar");
picker.FileTypeFilter.Add(".cbr");
picker.FileTypeFilter.Add(".cbz");
picker.FileTypeFilter.Add(".zip");
StorageFile pickfile = await picker.PickSingleFileAsync();
if (pickfile == null) { return; }
string pth = pickfile.Path;
FileInfo pickInfo = new FileInfo(pth);
try
{
ListRARs.Items.Clear();
using (var Arch = ArchiveFactory.Open(pickInfo))
{
foreach (IArchiveEntry a in Arch.Entries)
{
string thisKey = a.Key;
ListRARs.Items.Add(thisKey);
}
}
}
catch{ }
}
}
}
This is the first time I've used SharpCompress and I'm completely stumped. Any ideas anyone?

Access Denied when opening folder in UWP app

I have a simple UWP app that I want to open a folder to access all the files in with. I'm using the stock example code from Microsoft for how to make a folder picker in UWP. However, after picking the folder (any folder) and trying to access it I always get this exception:
System.UnauthorizedAccessException
HResult=0x80070005
Message=Access to the path 'T:\temp' is denied.
Source=System.IO.FileSystem
StackTrace:
at System.IO.Enumeration.FileSystemEnumerator`1.CreateDirectoryHandle(String path, Boolean ignoreNotFound)
at System.IO.Enumeration.FileSystemEnumerator`1..ctor(String directory, EnumerationOptions options)
at System.IO.Enumeration.FileSystemEnumerable`1..ctor(String directory, FindTransform transform, EnumerationOptions options)
at System.IO.Enumeration.FileSystemEnumerableFactory.FileInfos(String directory, String expression, EnumerationOptions options)
at System.IO.DirectoryInfo.InternalEnumerateInfos(String path, String searchPattern, SearchTarget searchTarget, EnumerationOptions options)
at System.IO.DirectoryInfo.EnumerateFiles()
at ShutterShock.MainPage.<Button_Click>d__1.MoveNext() in C:\Users\nixca\source\repos\ShutterShock\ShutterShock\MainPage.xaml.cs:line 37
Mainpage.xaml.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace ShutterShock
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
string path = await GetOpenLocation();
var boop = new DirectoryInfo(path);
boop.EnumerateFiles();
}
async Task<string> GetOpenLocation()
{
string returnText;
var folderPicker = new Windows.Storage.Pickers.FolderPicker();
folderPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop;
folderPicker.FileTypeFilter.Add("*");
Windows.Storage.StorageFolder folder = await folderPicker.PickSingleFolderAsync();
if (folder != null)
{
// Application now has read/write access to all contents in the picked folder
// (including other sub-folder contents)
Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(folder);
returnText = folder.Path;
}
else
{
returnText = "Operation cancelled."; //todo make this an exception, catch that exception
}
return returnText;
}
}
}
I get the exception on the "boop.EnumerateFiles();" line.
So of course right after posting this it came to me, but I'll leave this up because I didn't actually find an answer anywhere before asking. The Microsoft example is dumb, and unless all you want is the path of the folder, returning the path is useless. The UWP filepicker doesn't actually grant you System.IO level access to the folder, all it gives you is a StorageFolder you can work on. If you want to do anything useful, you need to return the StorageFolder object, you can use that to actually work on files. This is probably obvious to people who actually know what they're doing.
If you wan to get all files in a selected folder, then you can use folder.GetFilesAsync().
var folderPicker = new Windows.Storage.Pickers.FolderPicker();
folderPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop;
folderPicker.FileTypeFilter.Add("*");
StorageFolder folder = await folderPicker.PickSingleFolderAsync();
if (folder != null)
{
var files = await folder.GetFilesAsync();
foreach(var file in files)
{
Debug.WriteLine(file.Path);
}
}
Here is the my result.

CopyAsync method not working in my application

I am writing code to copy an mp3 file into the local folder of an application. I am trying to use the CopyAsync method to do this, but a red squiggly line appears underneath this method and I'm unsure of how to fix it. The error specifies that there is no accessible extension method. It then advises if I'm missing an assembly reference or a user directive.
I've found extensive information on this method through Microsoft, so I know it's possible. I'm brand new to building apps in C#, so I am not quite sure how to fix it.
My code is included below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
namespace MusicLibraryTest
{
public static class LibraryHelper
{
public static async void ChooseMusic()
{
//Music Library is opened on user's computer and displays all available mp3 files
var picker = new Windows.Storage.Pickers.FileOpenPicker
{
ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail,
SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.MusicLibrary
};
picker.FileTypeFilter.Add(".mp3");
//File is copied to local folder for use in music library
var file = picker.PickSingleFileAsync();
if (file != null)
{
await file.CopyAsync(ApplicationData.Current.LocalFolder);
}
}
Change this line:
var file = picker.PickSingleFileAsync();
To
var file = await picker.PickSingleFileAsync();
You're calling an async method that should be awaited.

Getting an Exception System.ComponentModel.Win32Exception : The system cannot find the file specified in Sikuli C#

I am getting an exception System.ComponentModel.Win32Exception : The system cannot find the file specified when i employ Sikuli in C# using selenium.
I have referred to other posts in Stack but i have not not got a solution for that.
I am also running VS 2017 in administrator mode
I have latest copy of Rest-Api Jar in /Debug folder.
Below is my code
using System;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Support.UI;
using Sikuli4Net.sikuli_REST;
using Sikuli4Net.sikuli_UTIL;
using SikuliModule;
namespace DownloadFile
{
public class Download
{
private IWebDriver driver;
private APILauncher launcher;
[SetUp]
public void setup()
{
driver = new FirefoxDriver();
launcher = new APILauncher(true);
driver.Navigate().GoToUrl("https://java.com/en/download/");
driver.Manage().Window.Maximize();
}
[Test]
public void TestMethod1()
{
new WebDriverWait(driver, TimeSpan.FromSeconds(60)).Until(ExpectedConditions.ElementExists((By.XPath("//span[contains(text(),'Free Java Download')]")))).Click();
new WebDriverWait(driver, TimeSpan.FromSeconds(60)).Until(ExpectedConditions.ElementExists((By.XPath("//span[contains(text(),'Agree and Start Free Download')]")))).Click();
launcher.Start();
Screen screen = new Screen();
Pattern Click_Save = new Pattern("C:/Selenium Files/Save.jpg");
screen.Wait(Click_Save, 500);
screen.Click(Click_Save);
launcher.Stop();
}
}
}
Update your path of .jpg file in below line of code:
Pattern Click_Save = new Pattern("C:\\Selenium Files\\Save.jpg");
Rest of the code seems fine.

Categories

Resources