B4J Question [ABMaterial] ABMUpload, Uploading to raspberrypi Problems

Hi there,
Im using ABMaterial to create web, running on my raspberry server.
I'm Trying to upload file from my laptop to server using ABMupload component, i only following tutorial on ABM website.
but somehow, the file is not uploaded.

here is my code. Btw in this code i'm using ABMupload and ABMFileInput. Both of that component have same problem (cannot upload to server )

B4X:
'Class module
Sub Class_Globals
    Private ws As WebSocket 'ignore
    ' will hold our page information
    Public page As ABMPage
    ' page theme
    Private theme As ABMTheme
    ' to access the constants
    Private ABM As ABMaterial 'ignore
    ' name of the page, must be the same as the class name (case sensitive!)
    Public Name As String = "FirmwareUpdaterPage"  '<-------------------------------------------------------- IMPORTANT
    ' will hold the unique browsers window id
    Private ABMPageId As String = ""
    
'    ' your own variables
'    Private myToastId As Int
    ' the download folder
'    Public DownloadFolder As String ="/www/" & ABMShared.AppName & "/uploads/"
    Public DownloadFolder As String ="uploads"
    Public DownloadMaxSize As String = 100*1024
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
    ' build the local structure IMPORTANT!
    BuildPage
End Sub

Private Sub WebSocket_Connected (WebSocket1 As WebSocket)
    Log("Connected")
    ws = WebSocket1
    ABMPageId = ABM.GetPageID(page, Name,ws)
    Dim session As HttpSession = ABM.GetSession(ws, ABMShared.SessionMaxInactiveIntervalSeconds)
    '----------------------START MODIFICATION 4.00-------------------------------
    If session.IsNew Then
        session.Invalidate
        ABMShared.NavigateToPage(ws, "", "./")
        Return
    End If
    '----------------------END MODIFICATION 4.00-------------------------------
    
    If ABMShared.NeedsAuthorization Then
        If session.GetAttribute2("IsAuthorized", "") = "" Then
            ABMShared.NavigateToPage(ws, ABMPageId, "../")
            Return
        End If
    End If
    
    ABM.UpdateFromCache(Me, ABMShared.CachedPages, ABMPageId, ws)
    If page.ComesFromPageCache Then
        ' when we have a page that is cached it doesn't matter if it comes or not from a new connection we serve the cached version.
        Log("Comes from cache")
        page.Refresh
        page.FinishedLoading
    Else
        If page.WebsocketReconnected Then
            Log("Websocket reconnected")
            ' when we have a client that doesn't have the page in cache and it's websocket reconnected and also it's session is new - basically when the client had internet problems and it's session (and also cache) expired before he reconnected so the user has content in the browser but we don't have any on the server. So we need to reload the page.
            ' when a client that doesn't have the page in cache and it's websocket reconnected but it's session is not new - when the client had internet problems and when he reconnected it's session was valid but he had no cache for this page we need to reload the page as the user browser has content, reconnected but we have no content in cache
            ABMShared.NavigateToPage (ws, ABMPageId, "./" & page.PageHTMLName)
        Else
            ' when the client did not reconnected it doesn't matter if the session was new or not because this is the websockets first connection so no dynamic content in the browser ... we are going to serve the dynamic content...
            Log("Websocket first connection")
            page.Prepare
            ConnectPage
        End If
    End If
    Log(ABMPageId)
    ' this page uses uploads, so needs some settings
    ws.Session.SetAttribute("abmcallback", Me)
    ws.Session.SetAttribute("abmdownloadfolder", DownloadFolder)
    ws.Session.SetAttribute("abmmaxsize", DownloadMaxSize)
End Sub

Private Sub WebSocket_Disconnected
    Log("Disconnected")
    ' and remove them again
    Try
        ws.Session.RemoveAttribute("abmcallback")
        ws.Session.RemoveAttribute("abmdownloadfolder")
        ws.Session.RemoveAttribute("abmmaxsize")
    Catch
        Log(LastException.Message)
    End Try
End Sub

Sub Page_ParseEvent(Params As Map)
    Dim eventName As String = Params.Get("eventname")
    Dim eventParams() As String = Regex.Split(",",Params.Get("eventparams"))
    If eventName = "beforeunload" Then
        Log("preparing for url refresh")
        ABM.RemoveMeFromCache(ABMShared.CachedPages, ABMPageId)
        Return
    End If
    Dim caller As Object = page.GetEventHandler(Me, eventName)
    If caller = Me Then
        If SubExists(Me, eventName) Then
            Params.Remove("eventname")
            Params.Remove("eventparams")
            ' BEGIN NEW DRAGDROP
            If eventName = "page_dropped" Then
                page.ProcessDroppedEvent(Params)
            End If
            ' END NEW DRAGDROP
            Select Case Params.Size
                Case 0
                    CallSub(Me, eventName)
                Case 1
                    CallSub2(Me, eventName, Params.Get(eventParams(0)))
                Case 2
                    If Params.get(eventParams(0)) = "abmistable" Then
                        Dim PassedTables As List = ABM.ProcessTablesFromTargetName(Params.get(eventParams(1)))
                        CallSub2(Me, eventName, PassedTables)
                    Else
                        CallSub3(Me, eventName, Params.Get(eventParams(0)), Params.Get(eventParams(1)))
                    End If
                Case Else
                    ' cannot be called directly, to many param
                    CallSub2(Me, eventName, Params)
            End Select
        End If
    Else
        CallSubDelayed2(caller, "ParseEvent", Params) 'ignore
    End If
End Sub

public Sub BuildTheme()
    ' start with the base theme defined in ABMShared
    theme.Initialize("pagetheme")
    theme.AddABMTheme(ABMShared.MyTheme)
    
    ' add additional themes specific for this page
    
End Sub

public Sub BuildPage()
    ' initialize the theme
    BuildTheme
    
    ' initialize this page using our theme
    page.InitializeWithTheme(Name, "/ws/" & ABMShared.AppName & "/" & Name, False, ABMShared.SessionMaxInactiveIntervalSeconds, theme)
    page.ShowLoader=True
    page.PageHTMLName = "index.html"
    page.PageTitle = "Update Firmware"
    page.PageDescription = ""
    page.PageKeywords = ""
    page.PageSiteMapPriority = ""
    page.PageSiteMapFrequency = ABM.SITEMAP_FREQ_YEARLY
        
    ' adding a navigation bar
    ABMShared.BuildNavigationBar(page, "Update Firmware Menu","../images/logoGTC.png", "", "Setting", "UpdateFirmware")
            
    ' create the page grid
    page.AddRows(3,True, "").AddCells12(1,"")
    page.BuildGrid 'IMPORTANT once you loaded the complete grid AND before you start adding components
        
    
End Sub

public Sub ConnectPage()
    ABMShared.ConnectNavigationBar(page)
    
    ' your stuff
    ' add header
    page.Cell(1,1).AddComponent(ABMShared.BuildHeader(page, "hdr1", "Update Firmware "))
    ' add Paragraph
    page.Cell(1,1).AddComponent(ABMShared.BuildParagraph(page, "par1", "Pilih File .jar untuk mengupdate firmware"))
    Dim upload1 As ABMUpload
    upload1.Initialize(page, "upload1", "Drop Here", "Browse", "upload")
    page.Cell(2,1).AddComponent(upload1)
    
    Dim inp1 As ABMFileInput
    inp1.Initialize(page, "inp1", "Select a file", "Open", True, "input", "button")
    page.Cell(3,1).AddComponent(inp1)
    
    page.Refresh ' IMPORTANT
    
    ' NEW, because we use ShowLoaderType=ABM.LOADER_TYPE_MANUAL
    page.FinishedLoading 'IMPORTANT
    
    page.RestoreNavigationBarPosition
End Sub

'Sub Page_Dropped(Params As Map)
'    If Params.Get("before") = "" Then
'        Log("'" & Params.Get("component") & "' moved from " & Params.Get("source") & " to " & Params.Get("target"))
'    Else
'        Log("'" & Params.Get("component") & "' moved from " & Params.Get("source") & " to " & Params.Get("target") & " before component " & Params.Get("before"))
'    End If
'End Sub

Sub inp1_Changed(value As String)
    Log("value : " & value)
    Dim inp1 As ABMFileInput  = page.Component("inp1")
    inp1.UploadToServer 'Here the file is uploading
    
End Sub


' clicked on the navigation bar
Sub Page_NavigationbarClicked(Action As String, Value As String)
    ' saving the navigation bar position
    page.SaveNavigationBarPosition
    If Action = "ABMUpload" Then Return
    If Action = "LogOff" Then
        ABMShared.LogOff(page)
        Return
    End If

    ABMShared.NavigateToPage(ws, ABMPageId, Value)
End Sub

Sub Page_FileUploaded(FileName As String, success As Boolean)
    If success Then
        Log ("File is Uploaded")
    Else
        Log ("File is Failed to Uploaded")
    End If
    page.ws.Flush '// IMPORTANT
End Sub
 
Thanks for your response btw
i realize the maximum file size, and for the trial i use the small size.
i running ABM demo on my laptop as server and running my program i posted before on my raspi as server
and then i uploaded exactly same file in both of them.
in demo it can be uploaded and save to /www/demo/uploads dir
but in raspi is like nothing happen.
even the log after page uploaded is not printed, both of them ( success or else)

B4X:
Sub Page_FileUploaded(FileName As String, success As Boolean)
    If success Then
        Log ("File is Uploaded")
    Else
        Log ("File is Failed to Uploaded")
    End If
    page.ws.Flush '// IMPORTANT
End Sub
 
Upvote 0

Harris

Expert
Licensed User
Longtime User
You should get a Success or Fail in the Page_FileUploaded method... (with no reason why).

How is your ABMUploadHandler treating your request? Does it allow the file type your requested?

Throw in logs to debug further...

Here are mine to study and possibly help. - ab is probably right with file size - since 100k is rather small...

B4X:
'**************
''' Handler...
'**************

Sub Handle(req As ServletRequest, resp As ServletResponse)   
    'get the callback page from the session (multiple modules can use this handler)
    Dim callback As Object = req.GetSession.GetAttribute("abmcallback")   
'    Dim downloadfolder As String = File.Combine(File.DirApp, req.GetSession.GetAttribute("abmdownloadfolder"))
    Dim downloadfolder As String          = File.Combine(File.DirApp, "/www/" & ABMShared.AppName & "/uploads/"&"comp_"&Main.comp_id)
    
'    Dim tdown As String = downloadfolder&"/comp_"&Main.comp_id
'    File.MakeDir(downloadfolder , "")
'    downloadfolder = tdown
    
    Log("download folder from Upload handler: "&downloadfolder)
    
    Dim MaxSize As Int
    Dim ActiveCaseNumber As String = ""
    Try
        MaxSize = req.GetSession.GetAttribute("abmmaxsize")
    Catch           
        resp.SendError(500, LastException.Message)
        Return
    End Try
    
    Try
        ActiveCaseNumber = ""' DateTime.Now 'req.GetSession.GetAttribute("abmactivecasenumber")
        If ActiveCaseNumber = Null Then
            ActiveCaseNumber = ""
        End If
    Catch           
        ActiveCaseNumber = ""
    End Try
    
    Dim data As Map   
    Dim fileName As String
    Dim tmpFileName As String
    DownLoadAllowedfiles.Initialize2(Array As String(".ZIP", ".PNG", ".JPG", ".JPEG", ".PDF"))
    Try
        Log(" what is max size: "&MaxSize)
        Try
           data = req.GetMultipartData(downloadfolder,  MaxSize)
              
        Catch
            Log(" Download Error: "&LastException.Message)
            
            If SubExists(callback, "Uploaderror") Then
                CallSubDelayed2(callback, "Uploaderror", ""&LastException.Message) ' , fileName, True)
            End If
            
            Return
        End Try       

        For i = 0 To data.Size -1
            Log(" what is data at: "&data.GetKeyAt(i)&"   "&data.GetValueAt(i))
        Next
        
        Dim filePart As Part = data.Get("upl")   
                
        If filePart.IsInitialized Then
            fileName =     filePart.SubmittedFilename
            tmpFileName = filePart.TempFile   
            Log(" what is temp file name: "&tmpFileName)   
            If IsAllowed(fileName) = False Then
                If SubExists(callback, "Del_Tempfile") Then           
                    CallSubDelayed3(callback, "Del_Tempfile",downloadfolder, tmpFileName)
                End If
                
'                If File.Delete( downloadfolder, tmpFileName) Then
'                  Log(" deleted temp file: "&tmpFileName)
'                Else
'                  Log(" file name not found to delete temp file: "&tmpFileName)
'                End If     
                
                If SubExists(callback, "Page_FileUploaded") Then           
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName&" - WRONG FILE TYPE! - ", False)
                End If
                'resp.SendError(500, "Not allowed")
                Return   
            End If           
            
            If ABM.HandleUpload( downloadfolder, tmpFileName, fileName) Then
                If SubExists(callback, "Page_FileUploaded") Then
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName, True)
                End If
            Else
                If SubExists(callback, "Page_FileUploaded") Then           
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName&" UNKNOWN ERROR! - ", False)
                End If
            End If           

        Else ' try image

            Dim filePart As Part = data.Get("imageFromCanvas")
            fileName = filePart.SubmittedFilename       
            tmpFileName = filePart.TempFile       
            If IsAllowed(fileName) = False Then
                If SubExists(callback, "Del_Tempfile") Then           
                    CallSubDelayed3(callback, "Del_Tempfile",downloadfolder, tmpFileName)
                End If
                
'                File.Delete( downloadfolder, tmpFileName)
                If SubExists(callback, "Page_FileUploaded") Then           
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName&" - BAD IMAGE - ", False)
                End If
                'resp.SendError(500, "Not allowed")
                Return   
            End If           
            If ABM.HandleUpload( downloadfolder, tmpFileName,  fileName) Then   
                If SubExists(callback, "Page_FileUploaded") Then
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName, True)
                End If
            Else
                If SubExists(callback, "Page_FileUploaded") Then           
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName&" - UNKNOWN IMAGE ERROR - " , False)
                End If
            End If   
        End If
        
    Catch       

        resp.SendError(500, LastException.Message)
        If SubExists(callback, "Page_FileUploaded") Then
            CallSubDelayed3(callback, "Page_FileUploaded", " - Unknown Error in File Name - ",  False)
        End If       
    End Try       
End Sub

Sub IsAllowed(fileName As String) As Boolean
    If DownLoadAllowedfiles.Size = 0 Then Return True
    For i = 0 To DownLoadAllowedfiles.Size - 1
        If fileName.ToUpperCase.EndsWith(DownLoadAllowedfiles.Get(i)) Then
            Return True
        End If
    Next
    Return False
End Sub

'************************
'  upload
'************************
'
Sub Page_FileUploaded(FileName As String, success As Boolean)   
'    Dim inp1 As ABMFileInput  = page.Component("fimgname")
'    inp1.Clear
'    Log(FileName & " = " & success)
    myToastId = myToastId + 1
    If success Then
        orgfname = FileName
        page.ShowToast("toast" & myToastId, "toastgreen", "File " & FileName & " uploaded!", 5000, False)
        Dim inp As ABMModalSheet = page.ModalSheet("newimage")
        Dim inp1 As ABMImage   = inp.Content.Component("thisimg")
        Dim inp2 As ABMInput   = inp.Content.Component("imgfilename")
        
        inp1.Source = "../uploads/" &"comp_"&Main.comp_id&"/"&FileName
    
        If File.Exists(File.DirApp&"/www/"&ABMShared.AppName&"/uploads/comp_"&Main.comp_id,FileName) Then
            Log(" file: exists "&FileName)
            inp2.Text = FileName
        Else
            Log(" no file exists")
            inp2.Text = ""
            
        End If       
        
        inp1.Refresh
        inp.Refresh
        
    Else
        page.ShowToast("toast" & myToastId, "toastred", "File " & FileName & " not uploaded!", 5000, False)
        orgfname = ""
    End If
    page.ws.Flush ' IMPORTANT
        
End Sub
 
Upvote 0
just a thought: what are your permissions on the upload folder on the pi?
upload_2018-10-30_16-55-32.png

this is the screen shoot of my www directory permision
 
Upvote 0
not always. I had a case where I've seen my www folders permissions did not allow everyone to write. I had copied the www folder to the pi logged in as user Pi, but was running it under another user who did not had write permissions.

After you say that, i change my www dir access permision to 777 (rwxrwxrwx) but is still same.
 
Upvote 0
1. Does it ever arrive in the handler?
2. What do the log()s say which Harris suggested you to add in the handler?
3. Do you get an error in the browser? (Chrome, F12, Console)

i run it in debug mode and i found some error that related in browser.

upload_2018-10-30_18-39-42.png

it's the log when i get in to page, and i think it's related to browser error. I'm sorry but i'm very new in this thing. can u help me please
upload_2018-10-30_18-40-45.png
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Where is your .jar file located? Your “uploads” folder? How are you starting your ABM program? With what user account?
 
Upvote 0
Where is your .jar file located? Your “uploads” folder? How are you starting your ABM program? With what user account?
i located my .jar in /home/pi directory
my upload folder in /home/pi/www/AIMRECEIVERrev6/uploads ==> AIMRECEIVERrev6 is the name of my app

if you mean sarting the program, is run it, i running it with sudo java -jar AIMRECEIVERrev6.jar on raspberry pi
- i build release ver on b4j,
- i copy it to raspberry
- sudo java -jar AIMRECEIVERrev6.jar
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
you did copy the whole www folder (with the js, css, fonts etc subfolders) to your pi too, didn't you?

You must also copy the .needs file next to your jar <--- I think this is the problem.

The .needs file contains some important info ABM extracted from your source code, and does need when run in release mode. The clue for me is in your error: sessioncreator.js, which is an relic from an earlier version of ABM.
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
my upload folder in /home/pi/www/AIMRECEIVERrev6/uploads ==> AIMRECEIVERrev6 is the name of my app
But that is not where you told the app where your folder is. You have your DownloadFolder set up to just “uploads”. The application is therefore looking for a download/upload folder relative to the location of your application. Try creating a /home/pi/uploads on your pi and see if your uploads happen.
 
Upvote 0
you did copy the whole www folder (with the js, css, fonts etc subfolders) to your pi too, didn't you?

You must also copy the .needs file next to your jar <--- I think this is the problem.

The .needs file contains some important info ABM extracted from your source code, and does need when run in release mode. The clue for me is in your error: sessioncreator.js, which is an relic from an earlier version of ABM.

Hi there...
Thx for your support, finnaly i can solve my problem.
i make a new ABM project and it running well with ABMUpload, so the problem maybe in my needs file like u say..
i think the problem is happen because im not copy file .need and www folder properly (i say this because i copy it before but not running well).
 
Upvote 0
But that is not where you told the app where your folder is. You have your DownloadFolder set up to just “uploads”. The application is therefore looking for a download/upload folder relative to the location of your application. Try creating a /home/pi/uploads on your pi and see if your uploads happen.

Thanks mate, but the directory path is correct because in UploadHandler Class there is the code line like this :

B4X:
Dim downloadfolder As String = File.Combine(File.DirApp, req.GetSession.GetAttribute("abmdownloadfolder"))

but thank for your suggestion, it make me more careful in my next project
 
Upvote 0
Top