Bug? jServer - Small file uploads are not written to disk unless they are queried

Fernando Solá

Member
Licensed User
Hello to everyone!

I have found a strange thing happening that I'd like to share and get feedback about from the comunity.

I have been recently working on a jServer application (with a fair amout of Websocket use) that will be receiving files to be processed. These files will range between 1kb and 30Mb. With larger files I have not seen this issue happening, but with smaller files, the uploaded files are not being written to disk until the file has been queried through a File method. I've compiled it on B4J 9.30 with JDK 8 and OpenJDK 11, ran it on OpenJDK and Java, tried it on a Windows 10 PC and also on a Linux Box (through b4j_bridge) using three different browsers, and I have been able to replicate the issue every time. In every case if the file is less than (around) 70kb it won't show on disk until the file has been queried for it's name, directory, size or existance. My guess is that the file is being held in a cache space within the server itself, but in any case it seems a weird behaviour. I have searched the forums for any similar issue, but I haven't been lucky.

I'm attaching a sample project with a few comments for testing. It is based on the File Upload with WebSockets from the ServerExample project posted by Erel so there is no weird code that could be causing the issue. Also, for convenience I've included a sample 1kb "Lorem Ipsum" text file inside the attached file.

I would really like to know a few things:
  • Can other people replicate it?
  • Is this issue a bug or an expected behaviour for this kind of scenarios?
  • Is there is any other way to circumvent it through the Part or the Handler object?

Thank you all for your comments and feedback!
 

Attachments

  • Sample.rar
    43.1 KB · Views: 124

alwaysbusy

Expert
Licensed User
Longtime User
I can see the same thing with your code, but never noticed it before as I immediately do the rename of the temp file to the real name. Asking for the part_File.Tempfile name is enough to flush the temp file.

So, with this code, it works:

B4X:
Private Sub File_Uploaded(Parts As Map)
    
    ws.Session.RemoveAttribute("file_upload")
    
    Dim part_File As Part = Parts.Get("input_file")
    
    If part_File.IsInitialized Then
        ' this line is key. Once you done this part, IsFile will be True
        Dim tempFile As String = part_File.TempFile
        
        If part_File.IsFile Then
            Dim folder As String = File.GetFileParent(tempFile)
            tempFile = tempFile.SubString(folder.Length + 1)
            Dim realFile As String = part_File.SubmittedFilename
            RenameFile(folder, tempFile, folder, realFile)
            Log("*** File successfully received ***")
            Log("Submitted: " & part_File.SubmittedFilename)
            Log("Received: " & part_File.TempFile)
            ws.Alert("File " & part_File.SubmittedFilename & " was received")
        Else
            LogError("File was not uploaded")
            ws.Alert("File was not uploaded")            
        End If        
    Else
        LogError("File was not uploaded")
        ws.Alert("File was not uploaded")
    End If
    
    ws.Flush
    
End Sub

' requires the JavaObject library
private Sub RenameFile(SourceFolder As String, SourceFile As String, TargetFolder As String, TargetFile As String) As Boolean
    Dim source, target As JavaObject
    source.InitializeNewInstance("java.io.File", Array(SourceFolder, SourceFile))
    target.InitializeNewInstance("java.io.File", Array(TargetFolder, TargetFile))
    Return source.RunMethod("renameTo", Array(target))
End Sub

Alwaysbusy
 
Top