B4J Question Get file with an impending download in a webView

jkhazraji

Active Member
Licensed User
Longtime User
If a webView has an impending file download on loading, or it has a link with the parameter download, like:
<a href="#" download="localfile.bin">Download file </a>,
It is not possible to download the file (localfile.bin) into b4j automatically or by clicking the link above.. so that
a SaveAs dialog box appears to prompt for the downloaded file name and location.
While this is possible in system web browser like Chrome.
To reproduce the problem just run the following code:


B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI
    Private Button1 As B4XView
    Private WebView1 As WebView
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
    Dim html As String=$"
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Document</title>
        </head>
        <body>
            <a href="#" download="local.text" >Download File</a>
        </body>
        </html>
    "$
    WebView1.LoadHtml(html)
    Wait For WebView1_PageFinished
    
End Sub

Sub Button1_Click
    xui.MsgboxAsync("Hello World!", "B4X")
End Sub
Is there a workaround?
 

drgottjr

Expert
Licensed User
Longtime User
there are workarounds and there are workarounds.
here's 1/2 of one using @Daestrum's famous bridge
contraption. the other half is up to you, and it's pretty
simple.

some comments:
fx's webview is not the same as android's, and neither
is a full-blown browser substitute.

to take over the default right click (aka, contextmenu)
event is relatively easy. to recreate a new contextmenu
is not trivial, but since what you want is to be able to
download a file referred to in the download attribute of
an anchor tag, you don't have to go to that trouble. you
just need to pass the name of the file back to b4j where
you can download it using jokhttputils2.

you need to inject javascript for the first part, and @Daestrum's
bridge for the second.

run the attached. depending on your level of experience, you'll
see what's going on. and note: my implementation is just one
of several ways of handling things.

you need to add a listener for right click (i added one for regular click
too). you need to disable the normal contextmenu and to determine
which anchor element was right clicked on (in your case, there was
only 1, but on a real webpage, there could be many). after you find
which element you clicked on, you need to find out the file name to
download. you pass that back to b4j using the bridge. once
safely back in b4j, you use jokhttputils2 to download the file.

what i've put together is based on your html code. obviously, there
is no real file to download. find a real site that uses the download
attribute and see if it works. i have no idea what happens if the
anchor tag doesn't use the download attribute.
 

Attachments

  • jsbridge.zip
    3.2 KB · Views: 16
Upvote 0

jkhazraji

Active Member
Licensed User
Longtime User
there are workarounds and there are workarounds.
here's 1/2 of one using @Daestrum's famous bridge
contraption. the other half is up to you, and it's pretty
simple.

some comments:
fx's webview is not the same as android's, and neither
is a full-blown browser substitute.

to take over the default right click (aka, contextmenu)
event is relatively easy. to recreate a new contextmenu
is not trivial, but since what you want is to be able to
download a file referred to in the download attribute of
an anchor tag, you don't have to go to that trouble. you
just need to pass the name of the file back to b4j where
you can download it using jokhttputils2.

you need to inject javascript for the first part, and @Daestrum's
bridge for the second.

run the attached. depending on your level of experience, you'll
see what's going on. and note: my implementation is just one
of several ways of handling things.

you need to add a listener for right click (i added one for regular click
too). you need to disable the normal contextmenu and to determine
which anchor element was right clicked on (in your case, there was
only 1, but on a real webpage, there could be many). after you find
which element you clicked on, you need to find out the file name to
download. you pass that back to b4j using the bridge. once
safely back in b4j, you use jokhttputils2 to download the file.

what i've put together is based on your html code. obviously, there
is no real file to download. find a real site that uses the download
attribute and see if it works. i have no idea what happens if the
anchor tag doesn't use the download attribute.
Thanks for you comment which is rich in valuable information, however, the file name is not enough to download it because you need the file link if you use jokhttputils2. The file name is actually set in the download attribute of the anchor tag but what matters is the initiation of the download process from the WebView to be resumed by b4j code. This is usually done by showing the SaveAs dialog in a full-blown browser prompting the user to choose the name and location where to save the file as he/ she clicks the anchor text.
Well, this is not done ( or not allowed) in a WebView even if you click the link. Some sites even do not show a link to click but pop up the SaveAs dialog as the page loads.
As I think they prepare the file and put it on a certain location in their server and hand over the link to the user ready to be downloaded through the SaveAs dialog.
One of the ‘narrow’ workarounds that I searched is to interrupt the download process and take over it but I was not successful to achieve that.
 
Last edited:
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
i'm disappointed you didn't see how to infer a link from the file name, if necessary.
 
Upvote 0

jkhazraji

Active Member
Licensed User
Longtime User
I appreciate your response and your code is great . So the first step is to infer the link from the file name and forward it to be downloaded with jokhttputils2.
but what is next?
Although the b4j.link2 did not get invoked.
 
Last edited:
Upvote 0
Top