Android Question okhttp issue, strange behaviour when req.InitializePost2 is used

OMS

Member
Hi,
I was trying to upload some image files from my b4a app to my B4J server.
Some files were uploaded successfully but some file upload with incorrect file size.
I noticed that when the first byte value is 0xFF , it will be omited and the file on the server will be one byte smaller than the source file.
My b4a app code is : (it used OKhttputils2)
B4X:
Sub UploadFile
    Log("File size is : " & File.Size(File.DirDefaultExternal, "myFile.jpg")) 
    Dim In As InputStream = File.OpenInput(File.DirDefaultExternal, "myFile.jpg")
    Dim data(In.BytesAvailable ) As Byte
    In.ReadBytes(data, 0, data.Length )

    Log( "data length = " & data.Length)
  
    Dim j As HttpJob
    j.Initialize("file", Me)
    j.PostBytes(link & "?type=file&filename=" & "myFile.jpg", data)
End Sub

and
server code is :
B4X:
Sub Handle(req As ServletRequest, resp As ServletResponse)
    If req.Method <> "POST" Then
        resp.SendError(500, "method not supported.")
        Return
    End If
    'we need to call req.InputStream before calling GetParameter.
    'Otherwise the stream will be read internally (as the parameter might be in the post body).
    Dim In As InputStream = req.InputStream
  
    Dim reqType As String = req.GetParameter("type")
    Select reqType
        Case "text"
            Dim tr As TextReader
            tr.Initialize(In)
            resp.Write("Message received successfully.")
        Case "file"
            Dim su As StringUtils
            Dim filename As String =su.DecodeUrl(req.GetParameter("filename"),"UTF8")
            If filename = "" Then
                resp.SendError(500, "Missing filename parameter")
                Return
            End If
            Dim out As OutputStream = File.OpenOutput(Main.filesFolder, filename, False)
            File.Copy2(In, out)
            out.Close
            resp.Write("OK, file uploaded successfully : " & filename & ", size=" & File.Size(Main.filesFolder, filename))
    End Select
End Sub

Result Log is
B4X:
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
File size is : 35300
data length = 35300
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
Success: OK, file uploaded successfully : myFile.jpg, size=35299
it is important that ant test be performed using diffrent image files including my attached image file
it seems that there is bug in okHttp library when OkHttpRequest object is initialized with InitializePost2 method
 

Attachments

  • myFile.jpg
    myFile.jpg
    34.5 KB · Views: 107

OMS

Member
Thank you for your reply
I changed my b4a code as you said:
B4X:
Sub UploadFile
    Log("File size is : " & File.Size(rp.GetSafeDirDefaultExternal(""), "myFile.jpg"))
    Log(rp.GetSafeDirDefaultExternal(""))
    Dim data() As Byte = File.ReadBytes(rp.GetSafeDirDefaultExternal(""), "myFile.jpg")
    Log( "data length = " & data.Length)
    
    Dim j As HttpJob
    j.Initialize("file", Me)
    j.PostBytes(link & "?type=file&filename=" & "myFile.jpg", data)
End Sub
but the problem persists, as you see the logs says that file on the server is 1 byte smaller than the source file
B4X:
** Activity (main) Resume **
File size is : 35300
/storage/emulated/0/Android/data/b4a.example/files
data length = 35300
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
Success: OK, file uploaded successfully : myFile.jpg, size=35299
 
Upvote 0

OMS

Member
1. [B4X] OkHttpUtils2 with Wait For

2. On the server side, try this:
B4X:
Dim In As InputStream = req.InputStream
Dim data() As Byte = Bit.InputStreamToBytes(in)
Log(data.Length)
'only here get the parameters.

I tried this, but it did not solve the problem šŸ™

I made another test , I added one extera byte to the beganing of the byte-array and file was ok on the server. but I know this is not a good way, it was just to test to see how many bytes will be missed on http upload
B4X:
Sub UploadFile
    Log("File size is : " & File.Size(rp.GetSafeDirDefaultExternal(""), "myFile.jpg"))
    Log(rp.GetSafeDirDefaultExternal(""))
    Dim data() As Byte = File.ReadBytes(rp.GetSafeDirDefaultExternal(""), "myFile.jpg")
    Log( "data length = " & data.Length)
    
    Dim data2(data.Length +1) As Byte
    Log( "data2 length = " & data2.Length)
    Dim mbyte As ByteConverter
    mbyte.ArrayCopy(data,0,data2,1,data.Length)
    data2(0)= 0xff

    Dim j As HttpJob
    j.Initialize("file", Me)
    j.PostBytes(link & "?type=file&filename=" & "myFile.jpg", data2)
End Sub
 
Upvote 0

OMS

Member
Thank you very much Erel,
Problem is Solved !!
When I was triming my web server big project to make it ready to send it for you I noticed that I was making a mistake on server side that must be avoided.

I had added filter :
B4X:
srvr.AddFilter("/*", "FilterUser", False)
and my mistake was reading parameters in FilterUser class module:
B4X:
    Try
        Dim UserCode As Int = req.GetParameter("User")
        If UserCode =5367 Then
            Return False
        Else
            Return True
        End if
    Catch
   
    End Try

This code prevents to read post stream correctly by other server handler modules.
I think B4J should detect this mistake and issue approprate warning :cool:
 
Last edited:
Upvote 0
Top