Is it possible to make WebView control to read local html files? - vb.net

I'm making an application with WebView control. And I want it to read local html file. But I can't find the right way to make it possible.
At first, I simply tried to use Navigate method and provide the file path in the "file:///~" format string as a parameter, but it didn't work.
https://learn.microsoft.com/ja-jp/windows/communitytoolkit/controls/wpf-winforms/webview-known-issues
This Microsoft page says that WebView control does not recognize "file:///~" protocol.
And it shows the 3 solutions to make WebView control to read local html files.
Use NavigateToLocal() method.
Use NavigateToLocalStreamUri() method.
Use NavigateToString() method.
I tried all of them, but each 3 have some issues that doesn't make it work.
NavigateToLocal method requires a RELATIVE path of the file (not the absolute path), relative from the application executable directory. So files in somewhere else from the application directory cannot be read by this method.
NavigateToLocalStreamUri method is not even implemented according to the page! I once tried it anyway, but it returned an exception and didn't work.
NavigateToString method can render the given html content string, but the external files like css, js, image files included by html codes cannot be loaded, so it does not provide a full function.
I found some sample of using NavigateToLocalStreamUri method and tried it by myself.
(VB.NET)
wvwMain.NavigateToLocalStreamUri(uri, New StreamUriResolver())
Public Class StreamUriResolver : Implements IUriToStreamResolver
Public Function UriToStream(uri As Uri) As Stream Implements IUriToStreamResolver.UriToStream
Return New FileStream(uri.LocalPath, FileMode.Open)
End Function
End Class
By this code, NavigateToLocalStreamUri method returns System.Resources.MissingManifestResourceException.
What I want to realize is very simple.
Using WebView control
Read local html file located anywhere on the local storage
And render the html file completely as an expected result
But I don't see the way right now.
I would appreciate your advises or helps.

The method NavigateToLocalStreamUri will not work. Please see https://learn.microsoft.com/en-us/windows/communitytoolkit/controls/wpf-winforms/webview-known-issues.
You have to use NavigateToLocal, but you will see a warning that it is deprecated. However, it does only work with relative paths. Is it possible for you to restructure your application so that you can use relative paths?
The NavigateToLocal method is the only way that I've found to call local HTML files in Microsoft.Toolkit.Forms.UI.Controls.Web WebView v6.0.

On Visual Studio 2019 Windows 10, the following VB.NET code works on my PC
Imports System.IO
Dim sFileName = Application.StartupPath & "/MyPage.html"
wv.NavigateToString(System.IO.File.ReadAllText(sFileName))
where wv is a WebView object.

Related

Replacing Absolute file path by Resource file path

I created an add-in to an existing software (Revit) and I want to embed an image (my company's logo) in the add-in's button.
Here is my current code for it:
'Set the large image shown on button
Dim uriImage As New Uri("\\10.8.60.3\Shared\REVIT\FSElogo.png")
Dim largeImage As New BitmapImage(uriImage)
MainButton.LargeImage = largeImage
It works pretty well and the logo is correctly displayed, however it requires the computer to have access to the server located at \\10.8.60.3. When working from home, we do not have access to this server and Revit throws an error when starting because of it.
So I tried adding the FSElogo.png file to my VB.Net project as a Resource and then tried to use My.Resources to access the image, effectively removing the need for an external image to be used.
Well, I can't get it to work.
I tried replacing the code above by
MainButton.LargeImage = CType(My.Resources.ResourceManager.GetObject("FSElogo.png"), Windows.Media.ImageSource)
But it doesn't work. It doesn't throw an error, but no image is displayed on the button.
If I don't cast my Object to an ImageSource I get an implicit conversion from Object to Image error, and I'm not even sure my ResourceManager is even really returning the object FSElogo.png.
What am I doing wrong here?
I am using the VS provided button with the .BackgroundImage property. Notice that the extension of the file is not included in the resource identifier. If this doesn't work, you will have to explain exactly how you added the resource to your project.
MainButton.BackgroundImage = My.Resources.FSElogo

download pdf file of blade instead of view in browser

I would like the browser to download file on button click of blade page. The following is used in controller and and added in provider file, but its showing in browser console but not downloading file.
use PDF;
// this controller
function sensorChartPDF(){
$pdf = PDF::loadView('sensorchartpdf');
return $pdf->download('invoice.pdf')->header('Content-Type','application/pdf');;
}
///// sensorchartpdf.blade.php this is view ///
https://canvasjs.com/javascript-charts/multi-series-spline-chart/
chart static code appened in this file
To signify to the web browser that the file should be downloaded and not displayed in line you have to specify the content-disposition header with a value of attachment.
Your question, however, does not appear to be purely a question regarding Dompdf. With Dompdf you would merely use the following:
$dompdf->stream("output.pdf", array('Attachment' => 1));
I'm providing this for anyone looking for similar issue when working with the library directly.
Since you're not using Dompdf directly but via another library so you'll need to specify exactly which library or framework you're using before somebody can provide an accurate answer.

Access MHT File from Solution Directory in Windows 8.1 App

I have an MHT (Microsoft web archive) file that I have added to my project folder. I need this file to display in a WebView on a help page. I have set the file's build action to "Content," like this question reccomended. I then use this code in the page's Loaded event handler.
Try
Dim strHelpNavigate = Path.Combine(Windows.ApplicationModel.Package.Current.InstalledLocation.ToString(), "\MyAppsHelp.mht")
webHelp.Navigate(New Uri(strHelpNavigate))
Catch ex As Exception
webHelp.NavigateToString("<html><head><style>body {font-family: segoe ui; color: white; background-color: black;}</style></head><body><h2>Sorry, the help page is currently unavailable.</h2></body></html>")
End Try
This code produces an exception: {"Invalid URI: The format of the URI could not be determined."}
I have also tried passing "\MyAppsHelp.mht" to the Navigate method like this question reccomended, but this produces the same exception, and I see from the Local window that the string passed to the Navigate method is the same either way.
Does anyone have any advice on how to display this file in the WebView?
WebView does not natively support HTML archive files, but you can do the work convert these files to html + images if you're so inclined.
Open the .mht file in notepad, and you'll see that there are separate sections for each part of the HTML file - you can parse these sections to get the HTML out, then the base64 encoded images, then save them in your local app folder and use WebView.NavigateToLocalStreamUri to load them. See http://blogs.msdn.com/b/wsdevsol/archive/2014/06/20/a-primer-on-webview-navigatetolocalstreamuri.aspx for details on how to use this method.
OF course, if it's a static file that you will be using all of the time, it would be far easier to just convert it before packaging the app.

Unraveling the confusion about Embedded Resources

EDIT: Read answer number 1 from Tim Schmelter and then use this question for examples of how to embed resources and access them at runtime.
The subject of embedded resources comes up a lot, especially with people asking how to access the embedded files at runtime. Things get more confusing because Visual Studio gives you 2 different ways of embedding a resource, and different ways of accessing those resources at runtime. The problem is that depending on which method you used to embed the resource, the method you’re trying to use to access the file at runtime might not work. This post is an attempt to clear up all the confusion that I see out there, but I also have a question that nobody can seem to answer factually: Why is the size of my compiled program TWICE the size of the embedded resource (sometimes)? For example if I embed a 20MB file into my project, why does my program compile to 40MB? I haves asked this question in the past and nobody was able to reproduce my results. I found that the reason they were not able to reproduce was because they were embedding the file in a different way. See here:
Method 1:
Double-click on My Project to open the property pages and go to the Resources Tab. Now click Add Resource > Add Existing File. Browse to the file you want to embed. For this example I’m using an executable. You will now see your file on the Resources Tab:
You will also see that a folder named Resources was created under your project and the embedded file has been placed in this folder:
EDIT: THIS NEXT STEP WAS THE PROBLEM. TURNS OUT THAT WHEN YOU ADD A FILE VIA THE RESOURCES TAB YOU SHOULD NOT SET THE BUILD ACTION TO EMBEDDED RESOURCE. Counter intuitive to say the least!
Now with the file selected, look down at the properties window for the file and change the build action to Embedded Resource: (this step should ONLY be performed when you add a file via method 2).
Now compile your program. You will see that the size of your compiled program is at least double the size of your embedded resource. This does not happen with method 2. See here:
Method 2:
Right-click on your project name and choose Add > Existing Item. Browse to your file, and this time you will notice that while it was indeed placed under your project, there was no Resources folder created:
Now once again select the file and change the Build Action to Embedded Resource and compile. This time the size of the compiled program will be as you expected - about the size of the embedded file and not double the size as with method 1.
Which method you use to embed your file will determine which method you can use to access the file at runtime. For method 1 this is very simple, all you have to do is:
My.Computer.FileSystem.WriteAllBytes(Path, My.Resources.ResourceName, Append)
Where Path is the location and name for the file you want to save on the harddrive, ResourceName is the name of the embedded resource that you see in the project window (minus any extension), and Append is whether or not you want to create a new file or overwrite an existing file. So for example, using test.exe from the above images, I could save that file to the C drive like this:
My.Computer.FileSystem.WriteAllBytes(“C:\test.exe”, My.Resources.test, False)
Couldn’t be easier.
Method 2 however doesn’t appear to give you access to My.Resources so it gets a little more complicated. You have to create a Stream to hold the resource, put the stream into a byte array, then write the bytes out to the file system. The simplest way I have found to do this is like this:
Using s As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Project.ResourceName)
Dim bytes(s.Length) As Byte
s.Read(bytes, 0, bytes.Length)
File.WriteAllBytes(OutputFile, bytes)
End Using
With this method ResourceName must contain the file extension AND project name so using our example from above we can just do:
Using s As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(WindowsApplication1.test.exe)
Dim bytes(s.Length) As Byte
s.Read(bytes, 0, bytes.Length)
File.WriteAllBytes(“C:\test.exe”, bytes)
End Using
Text-based files are a little different:
Dim output As String
Using sr As StreamReader = New StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(WindowsApplication1.test.txt))
output = sr.ReadToEnd()
End Using
Using sw As StreamWriter = New StreamWriter(“C:\test.txt”)
sw.Write(output)
End Using
Having struggled with this in the past I hope this will help someone. And if you think you can explain factually why method 1 of embedding a resource bloats my compiled program to double its size, I would really appreciate it.
I assume that Method 1 is adding the files twice.
http://www.vbdotnetforums.com/vb-net-general-discussion/42670-visual-basic-net-2008-get-resource-file-io-stream.html#post121923
At least that is the conclusion of the thread above.
Quote:
You went to the Resources page of the project properties and added the files there, right? You then went into the Solution Explorer and change the Build Action of the files to Embedded Resource, right? That's why you were doubling the file size: you were adding each file twice.
There are two different ways to add resources: on the Resources page of the project properties and in the Solution Explorer. You do NOT do both. If you want to use GetManifestResourcestream then you do NOT use the Resources page. You add the files to the project in the Solution Explorer manually, then you set the Build Action to Embedded Resource.
In future, do one or the other, not both.
Add a file to the Resources page of the project properties and then access it via My.Resources. This will automatically add the file to the project in the Solution Explorer but the Build Action will be None and it should be left that way.
Add the file to the project in the Solution Explorer by using Add New Item or Add Existing Item. Set the Build Action of the file to Embedded Resource and then access the resource using GetManifestResourceStream.
Just an update for anyone who wants to use this code. The code actually writes one additional byte to the file due to zero-based declaration of the byte array.
To get an exact copy of the original file change the code to:
Using s As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(WindowsApplication1.test.exe)
Dim bytes(s.Length-1) As Byte
s.Read(bytes, 0, bytes.Length)
File.WriteAllBytes(“C:\test.exe”, bytes)
End Using

Saving a user edited text field to a .js file in iOS

I'm creating an iOS5 app (programmed in Objective-C) which provides a couple of functions. One of them is to allow a user to fill out a text field with JavaScript. When the user presses a "Test" button, I want it to save to a specific JS file and move to a new view, displaying an HTML page that will display the results of that JavaScript on a canvas element.
Unfortunately for me, I have no idea how to save to a JS file for a text field. Nor do I know if this is actually the best way to achieve the results I'm after.
So can anyone tell me the code I'd need to place in the IBAction of my test button to save the file, or if there is a better way to get the user's script into the HTML file with the canvas element?
You have some options to do that.
Add a callback in WebView is possible only in desktop apps, but you can make a workaround.
1- Set a handler to click in javascript;
2- This handler parse the value via windows.location (trying to change the current url);
3- In UIWebviewDelegate set webView:shouldStartLoadWithRequest:navigationType: to recognize this values parsed by javascript and returning NO (canceling the url change).
After you have the code typed by user, is easier pass to the new one UIWebView. You can save the file via NSData or other class and load in by the path, or you can parse directly the code to be showed via NSString.
EDIT
I, still, belive what I said is what you want, but with a little more info. Yes, 3 NSString probably solve your problem. You even can call eval in javascript, via objective-c and parse user code too. Those logic ideas are a good approaching. You can choose the easier for you.
There are more info in this another Q&A
You can use html 5 local storage for that.