B4J Question [ABMaterial] 4.0 problem with download file in mobile

MichalK73

Well-Known Member
Licensed User
Longtime User
Hello.
Again I met another problem that I can not understand.
I press LABEL on the page and should send the specified file to the user. Everything is fine and the file is right in the PC browser, but when doing the same thing on the mobile browser (Android) it's getting messy.

Sub for click label:
B4X:
Sub zal1_Clicked(Target As String)
    Dim lista As List
    Dim zal As ABMLabel = page.Component("zal1")
    lista = DBM.SQLSelect(DBM.GetSQL, "select file1, orginal_file1 from message where idx=?", Array As String(zal.Tag))
    Dim m As Map = lista.Get(0)
    Dim link As String = "../../send?file1="&m.Get("file1")&"&file2="&m.Get("orginal_file1")
    ABMShared.NavigateToPage (ws, "", link)
    'Log (folder & FileName)
 
End Sub

B4X:
'----------------------START MODIFICATION 4.00-------------------------------
Public Sub NavigateToPage(ws As WebSocket, PageId As String, TargetUrl As String) 'ignore   
    Dim testTargetUrl As String = TargetUrl
    If Not(testTargetUrl.EndsWith(".htm") Or testTargetUrl.EndsWith(".html") Or testTargetUrl.EndsWith("/")) Then
        TargetUrl = TargetUrl & "/"
    End If
    If PageId.Length > 0 Then ABM.RemoveMeFromCache(CachedPages, PageId)
    If ws.Open Then
        ' it doesn't keep navigation history in the browser (the back button exists the application)
        'ws.Eval("window.location.replace(arguments[0])", Array As Object(TargetUrl))
        ' if you need browser history just comment the lines above and uncomment the lines below
        ' it keeps the navigation history in the browser
        ws.Eval("window.location = arguments[0]", Array As Object(TargetUrl))
        ws.Flush
        'ws.Close ' ALSO NEW 4.00   
    End If   
End Sub
'----------------------END MODIFICATION 4.00-------------------------------

In Main is:
B4X:
srvr.AddHandler("/send", "send", True)

Handler 'send':
B4X:
Sub Class_Globals
End Sub

Public Sub Initialize
End Sub

Sub Handle (req As ServletRequest , resp As ServletResponse)

    Dim FileName As String = req.GetParameter("file1")
    Dim FileName2 As String = req.GetParameter("file2")
    Dim Folder As String = File.DirApp & "\www\" & ABMShared.AppName & "\uploads\"
    If File.Exists (Folder, FileName) = True Then
        Dim In As InputStream = File.OpenInput (Folder, FileName)
        resp.SetHeader ( "Content-Type", "application/xxx")
        resp.SetHeader ( "Content-disposition", "filename="""&FileName2&"""")
        File.Copy2 (In, resp.OutputStream)
    Else
    End If
End Sub

Error for mobile:
B4X:
Error occurred on line: 19
org.eclipse.jetty.io.EofException
    at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:292)
    at org.eclipse.jetty.io.WriteFlusher.flush(WriteFlusher.java:429)
    at org.eclipse.jetty.io.WriteFlusher.completeWrite(WriteFlusher.java:384)
    at org.eclipse.jetty.io.ChannelEndPoint$3.run(ChannelEndPoint.java:139)
    at org.eclipse.jetty.util.thread.Invocable.invokePreferred(Invocable.java:128)
    at org.eclipse.jetty.util.thread.Invocable$InvocableExecutor.invoke(Invocable.java:222)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:294)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:199)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:673)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:591)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: Istniejące połączenie zostało gwałtownie zamknięte przez zdalnego hosta
    at sun.nio.ch.SocketDispatcher.writev0(Native Method)
    at sun.nio.ch.SocketDispatcher.writev(SocketDispatcher.java:55)
    at sun.nio.ch.IOUtil.write(IOUtil.java:148)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:504)
    at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:272)
    ... 10 more

What could be the reason?
 

OliverA

Expert
Licensed User
Longtime User
Caused by: java.io.IOException: Istniejące połączenie zostało gwałtownie zamknięte przez zdalnego hosta
Translated: The existing connection was abruptly closed by the remote host

See (https://stackoverflow.com/a/27907345)

Seems to happen to other languages (.NET) (https://briancaos.wordpress.com/201...ction-was-forcibly-closed-by-the-remote-host/)

This points to caching on the server (https://groups.google.com/forum/#!topic/neo4j/3h-_PCrb6p4). Has something changed in caching?

Just some of the Google Foo Finds.
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
Translated: The existing connection was abruptly closed by the remote host

See (https://stackoverflow.com/a/27907345)

Seems to happen to other languages (.NET) (https://briancaos.wordpress.com/201...ction-was-forcibly-closed-by-the-remote-host/)

This points to caching on the server (https://groups.google.com/forum/#!topic/neo4j/3h-_PCrb6p4). Has something changed in caching?

Just some of the Google Foo Finds.

YES, the major v4 changes are in fact related to cache management...
 
Upvote 0

MichalK73

Well-Known Member
Licensed User
Longtime User
YES, the major v4 changes are in fact related to cache management...

Can somebody disable the cache in ABMaterial 4.0 for this download feature ??
I noticed that the Chrome (Android) trial is running fine and the file is downloaded from the server. However, I'm using WebView (B4A) in B4A application and this is causing bugs (broken connection).
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
Can somebody disable the cache in ABMaterial 4.0
No, this is not possible and I'm not even convinced it could have anything to do with this. Have you tried using false instead of true in srvr.AddHandler("/send", "send", True)? Note that webview is not a full blown web browser and I never can guarantee ABM will work in it. Also, add a log(req.requesruri) in the AMcacheControl class and see what it happens there.
 
Upvote 0

mindful

Active Member
Licensed User
Maybe it's because the navigate to page adds a / to your link:

B4X:
If Not(testTargetUrl.EndsWith(".htm") Or testTargetUrl.EndsWith(".html") Or testTargetUrl.EndsWith("/")) Then
 TargetUrl = TargetUrl & "/"
End If
 
Upvote 0

MichalK73

Well-Known Member
Licensed User
Longtime User
maybe you should redirect the user to the file url
It's not that easy. W / uploads / are files with random names other than the original ones. Hence, the procedure is FileName1 (random name on HDD) and FileName2 (original name), and when I download it I change the name eg 'jkdfksdbfksdbfksdbf' to 'report.pdf'.
srvr.AddHandler("/send", "send", True)?
I probably already checked but I do not remember, I will try to check.
Maybe it's because the navigate to page adds a / to your link:
I've seen that before, so I added 3 fictional parameters later
B4X:
Dim link As String = "../../send?file1="&m.Get("file1")&"&file2="&m.Get("orginal_file1")&"&zero=0"
 
Upvote 0

MichalK73

Well-Known Member
Licensed User
Longtime User
Change to
B4X:
srvr.AddHandler("/send", "send", False)
The effect is the same.

Strange that Chrome (Android) works on the system browser and WebView (B4A) disconnects. Maybe we should add some new resp.SetHeader value to work?
 
Last edited:
Upvote 0

MichalK73

Well-Known Member
Licensed User
Longtime User
B4X:
Sub Handle (req As ServletRequest , resp As ServletResponse)

    Dim FileName As String = req.GetParameter("file1")
    Dim FileName2 As String = req.GetParameter("file2")
    Dim Folder As String = File.DirApp & "\www\" & ABMShared.AppName & "\uploads\"
    If File.Exists (Folder, FileName) = True Then
        Dim Ina As InputStream = File.OpenInput (Folder, FileName)
        resp.SetHeader ( "Content-Type", "application/x-download")
        'resp.ContentType = "application/xxx"
        'resp.SetHeader("Content-Description", "File Transfer")
        'resp.SetHeader("Content-Transfer-Encoding","binary")
        'resp.SetHeader("Cache-Control", "no-cache, must-revalidate")
        resp.SetHeader ( "Content-disposition", "filename="""&FileName2&"""")
        resp.SetHeader ( "Connection", "keepalive")
        resp.SetHeader ("Expires", "1000")
        resp.SetHeader ("Refresh", "3")
        Dim length As Int = File.Size(Folder,FileName)
        resp.ContentLength = length
        File.Copy2 (Ina, resp.OutputStream)
    Else
    End If
End Sub

The effect is the same.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Your probably going to need some error log off of your phone to see why. The phone is doing the disconnecting, not the server. Without some sort of log, it's just a guessing game. There is a resp.ContentType property (instead of SetHeader), but that should not be an issue?
 
Upvote 0

MichalK73

Well-Known Member
Licensed User
Longtime User
OK.
Apparently there is a bug in Android, a waste of time on it. The webapp will block links as will the mobile browser and in the B4A will add some code and otherwise break the appendix. Possible by NativeControler ABMaterial <-> B4A ??
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
I have been trying things all morning and indeed, it appears the Webview does not allow receiving a file like this. But maybe you can catch the download from inside B4A and download the file from there using okHttpUtils2? Here, viewer is a WebView. My B4A is a bit rusty so could be made better ;)

B4A
B4X:
Sub Viewer_OverrideUrl (Url As String) As Boolean  
   If Url.Contains("uploads/") Then
     ' we need to download a file
     Log(Url)
     Dim i As Int = Url.IndexOf("&file2=")
     Dim NewName As String = Url.SubString(i + 7)
     Url = Url.SubString2(0,i)
     DownLoadfile(Url, NewName)
     Return True
   End If
   Return False
End Sub

Sub DownLoadfile(Url As String, newName As String)
   Dim job As HttpJob
   job.Initialize("", Me) 'note that the name parameter is no longer needed.
   job.Download(Url)
   Wait For JobDone(job As HttpJob)
   If job.Success Then
     Dim fOut As OutputStream
     fOut = File.OpenOutput(File.DirRootExternal & "/Download", newName, False)
     File.Copy2(job.GetInputStream, fOut)
     fOut.Close
     Msgbox(newName, "downloaded")    
   End If
   job.Release
End Sub

B4J
B4X:
Sub btn_Clicked(Target As String)
   Dim link As String = $"../uploads/othername.pdf&file2=newName.pdf"$
   ABMShared.NavigateToPage (ws, "", link)
End Sub

NOTE: in ABMShared I have remove this + ws.close (you could check the url and only not close it if it contains upload/):
B4X:
'   Dim testTargetUrl As String = TargetUrl
'   If Not(testTargetUrl.EndsWith(".htm") Or testTargetUrl.EndsWith(".html") Or testTargetUrl.EndsWith("/")) Then
'     TargetUrl = TargetUrl & "/"
'   End If
 
Upvote 0
Top