B4J Question [ABMaterial] ABMUpload fires Page_FileUploaded twice upon failure (size)

OliverA

Expert
Licensed User
When uploading a file that is too large, Page_FileUploaded is invoked twice. Once by the catch block in ABMUploadHander. Another time through the Page_ParseEvent method of the page containing the ABMUpload component. I'm guessing that the ABMUpload component is issuing this call to the page (since I can't find anywhere else that is invoking Page_ParseEvent). The call from ABMUploadHandler has the FileName set to the LastException.Message and success set to False. The second call has the FileName set to the filename of the file that failed to upload and success set to False. Note: In Debug mode, the calls are reversed, with the Page_ParseEvent occurring before the call (via CallSubDelayed3) from ABMUploadHandler.

Edit: Forgot to add: ABM v4.51
 
Last edited:

OliverA

Expert
Licensed User
I've set the size up to 500K, but uploaded files larger than that just to see what happens. I also ran the Demo (after this) and noticed that on failure (due to size) two chips would pop up, one stating "File java.lang.IllegalStateException: Request exceeds maxRequestSize (102400) not uploaded!" and then "File abcdefg.jpg not uploaded!". Please note that the ABMFileInput does not invoke Page_FileUploaded twice when the file size is too large.
 

Cableguy

Expert
Licensed User
What would be the exact steps to reproduce this? I have a project in hands that will also need file uploading, and you got me worried
 

OliverA

Expert
Licensed User
Note: All this taken from the Demo program
1) Add a couple of globals
B4X:
Public DownloadFolder As String = "/www/" & ABMShared.AppName & "/uploads/"
Public DownloadMaxSize As String = 500*1024
2) Make sure the directory exists as set in #1
3) In a ) WebSocket_Connected where it logs
B4X:
Log("Websocket first connectoin")
or b) if you use ConnectPage
place the following code before page.Refresh (placement may not be important, I'm just following Demo code)
B4X:
page.ws.session.SetAttribute("abmcallback", Me)
page.ws.session.SetAttribute("abmdownloadfolder", DownloadFolder)
page.ws.session.SetAttribute("abmmaxsize", DownloadMaxSize)
4) Create an ABMUpload compenent and place it
Sample code:
B4X:
' create the upload
Dim upload As ABMUpload
upload.Initialize(page, "upload", "Drop Here", "Browse", "")
upl.Content.CellR(0,1).AddComponent(upload)
5) Add you Page_FileUploaded method (to the same page the ABMUpload component is placed):
B4X:
Sub Page_FileUploaded(FileName As String, success As Boolean)
   Log("Page_FileUploaded")
   If success Then
       Log($"${FileName} has been successflly uploaded"$)
   Else
       Log($"File ${FileName} not uploaded!"$)
   End If
End Sub
6) Enjoy the double call of Page_FileUploaded when the file size is too large
and you got me worried
If you are doing more than displaying a failure message, then it could be an issue (since you would duplicate your failure mitigation code). Otherwise you are just posting two notifications per failure.
 

alwaysbusy

Expert
Licensed User
Not a real bug in ABM. It is the second Try Catch that also calls Page_FileUploaded (on the line data = req.GetMultipartDate(downloadFolder, MaxSize)).
You can remove the 'If SubExists(callback, "Page_FileUploaded") Then' if you want.

Or, you can check the size first before running the GetMultipartData command:
B4X:
   ...
   If req.ContentLength > MaxSize Then
       resp.SendError(500, "Error")
       Return
   End If

   Try
       data = req.GetMultipartData(downloadfolder, MaxSize)   
       ...
This should call the Page_FileUploaded() only once.
 
Top