B4J Question B4J Post Multipart File works in Debug mode but not in Release And Release Obfuscated mode

hatzisn

Well-Known Member
Licensed User
Longtime User
Hello to everyone,

please consider the following code. It is placed in a UI application. This code posts a file in a server with a multipart job (it is derived from an example of Erel) along with some name-value pairs. When I run it in debug mode I get response from "Wait For" in Sub GetTheResponse, but in release and release obfuscated mode, I get no response. What is wrong???? Here is the code:

B4X:
Public Sub GetTheResponse(assr As String, Directory As String, Filename As String, ActCase As Boolean)
 
    'The following two are global variables
    TempCounter = 0
    TrackerIndex = 0
 
    Dim fd As MultipartFileData
    fd.Initialize
    fd.KeyName = "file"
    fd.Dir = Directory
    fd.FileName = Filename
 
    Dim NameValues As Map
    NameValues.Initialize
    NameValues.Put("value1", "tp1resp")
    NameValues.Put("assurance", assr)
 
    Dim sURL As String
    Select Case ActCase
        Case False
            sURL = "https://api.myserver.com/getdata1"
        Case True
            sURL = "https://api.myserver.com/getdata2"
    End Select
 
    Dim job As HttpJob = CreateMultipartJob(sURL, NameValues, Array(fd))
    job.GetRequest.SetHeader("Authorization", $"Bearer 12312414ghv1c24h122421h3c1hc4g1h4g2214"$)
    Log("1")
    Wait For (job) JobDone (job As HttpJob)
    Log("2")
    Log(job)
    Log(job.GetString)
    File.Delete(xui.DefaultFolder, job.Tag)
    job.Release
End Sub


Public Sub CreateMultipartJob(Link As String, NameValues As Map, Files As List) As HttpJob
    Dim boundary As String = "---------------------------1461124740692"
    TempCounter = TempCounter + 1
    Dim TempFileName As String = "post-" & TempCounter
    Dim stream As OutputStream = File.OpenOutput(xui.DefaultFolder, TempFileName, False)
    Dim b() As Byte
    Dim eol As String = Chr(13) & Chr(10)
    Dim empty As Boolean = True
    If NameValues <> Null And NameValues.IsInitialized Then
        For Each key As String In NameValues.Keys
            Dim value As String = NameValues.Get(key)
            empty = MultipartStartSection (stream, empty)
            Dim s As String = _
$"--${boundary}
Content-Disposition: form-data; name="${key}"

${value}"$
            b = s.Replace(CRLF, eol).GetBytes("UTF8")
            stream.WriteBytes(b, 0, b.Length)
        Next
    End If
    If Files <> Null And Files.IsInitialized Then
        For Each fd As MultipartFileData In Files
            empty = MultipartStartSection (stream, empty)
            Dim s As String = _
$"--${boundary}
Content-Disposition: form-data; name="${fd.KeyName}"; filename="${fd.FileName}"
Content-Type: ${fd.ContentType}

"$
            b = s.Replace(CRLF, eol).GetBytes("UTF8")
            stream.WriteBytes(b, 0, b.Length)
            Dim in As InputStream = File.OpenInput(fd.Dir, fd.FileName)
            File.Copy2(in, stream)
        Next
    End If
    empty = MultipartStartSection (stream, empty)
    s = _
$"--${boundary}--
"$
    b = s.Replace(CRLF, eol).GetBytes("UTF8")
    stream.WriteBytes(b, 0, b.Length)
    Dim job As HttpJob
    job.Initialize("", Me)
    stream.Close
    Dim length As Int = File.Size(xui.DefaultFolder, TempFileName)
    Dim in As InputStream = File.OpenInput(xui.DefaultFolder, TempFileName)
    Dim cin As CountingInputStream
    cin.Initialize(in)
    Dim req As OkHttpRequest = job.GetRequest
    req.InitializePost(Link, cin, length)
    req.SetContentType("multipart/form-data; boundary=" & boundary)
    req.SetContentEncoding("UTF8")
    TrackProgress(cin, length)
    job.Tag = TempFileName
    CallSubDelayed2(HttpUtils2Service, "SubmitJob", job)
    Return job
End Sub

Private Sub MultipartStartSection (stream As OutputStream, empty As Boolean) As Boolean
    If empty = False Then
        stream.WriteBytes(Array As Byte(13, 10), 0, 2)
    Else
        empty = False
    End If
    Return empty
End Sub

Private Sub TrackProgress (cin As CountingInputStream, length As Int)
    TrackerIndex = TrackerIndex + 1
    Dim MyIndex As Int = TrackerIndex
    Do While MyIndex = TrackerIndex
        Log($"$1.2{cin.Count * 100 / length}%"$)
        If cin.Count = length Then Exit
        Sleep(100)
    Loop
End Sub
 
Last edited:

MicroDrie

Well-Known Member
Licensed User
The first challenge is that when you obfuscate the program code, a variable must start with a underscore.
Second, you must be careful when choosing a variable name that should not match a reserved word.
Furthermore, the problem could also be caused by the fact that the release version runs faster than in debug mode. I would add more log commands earlier to determine if things are going wrong before your current log.
 
Upvote 0

hatzisn

Well-Known Member
Licensed User
Longtime User
Hi, thanks for the response... Ok, I have done all these things. I just changed that the underscore is placed after the variable followed by 1 i.e. "_1". The result though in the responses is the same... Now the code looks like this:

Edit - I also logged the jobs in two consecutive compilations and compared the logs with this tool - they are the same except from the hecadecimal IDs:

https://text-compare.com/

B4X:
Public Sub GetTheResponse(assr_1 As String, Directory_1 As String, Filename_1 As String, ActCase_1 As Boolean)
 
    'The following two are global variables
    TempCounter = 0
    TrackerIndex = 0
 
    Dim fd As MultipartFileData
    fd.Initialize
    fd.KeyName = "file"
    fd.Dir = Directory_1
    fd.FileName = Filename_1
 
    Dim NameValues As Map
    NameValues.Initialize
    NameValues.Put("value1", "tp1resp")
    NameValues.Put("assurance", assr_1)
 
    Dim sURL As String
    Select Case ActCase_1
        Case False
            sURL = "https://api.myserver.com/getdata1"
        Case True
            sURL = "https://api.myserver.com/getdata2"
    End Select
 
    Dim job As HttpJob = CreateMultipartJob(sURL, NameValues, Array(fd))
    job.GetRequest.SetHeader("Authorization", $"Bearer 12312414ghv1c24h122421h3c1hc4g1h4g2214"$)
    Log("1")
    Wait For (job) JobDone (job As HttpJob)
    Log("2")
    Log(job)
    Log(job.GetString)
    File.Delete(xui.DefaultFolder, job.Tag)
    job.Release
End Sub

Public Sub CreateMultipartJob(sURL As String, NameValues As Map, FilesList As List) As HttpJob
    Dim boundary_1 As String = "---------------------------1461124740692"
    TempCounter = TempCounter + 1
    Dim TempFileName_1 As String = "post-" & TempCounter
    Dim str_1 As OutputStream = File.OpenOutput(xui.DefaultFolder, TempFileName_1, False)
    Dim b_1() As Byte
    Dim eol_1 As String = Chr(13) & Chr(10)
    Dim empty_1 As Boolean = True
    Dim s_1 As String
    If NameValues <> Null And NameValues.IsInitialized Then
        For Each k As String In NameValues.Keys
            Dim value_1 As String = NameValues.Get(k)
            empty_1 = MultipartStartSection (str_1, empty_1)
            Log("1.Empty_1=" & empty_1)
            s_1 = _
$"--${boundary_1}
Content-Disposition: form-data; name="${k}"

${value_1}"$
            Log($"Key=${k}, s_1=${s_1}"$)
            b_1 = s_1.Replace(CRLF, eol_1).GetBytes("UTF8")
            str_1.WriteBytes(b_1, 0, b_1.Length)
        Next
    End If
    If FilesList <> Null And FilesList.IsInitialized Then
        For Each fd As MultipartFileData In FilesList
            empty_1 = MultipartStartSection (str_1, empty_1)
            Log("2.Empty_1=" & empty_1)
            s_1 = _
$"--${boundary_1}
Content-Disposition: form-data; name="${fd.KeyName}"; filename="${fd.FileName}"
Content-Type: ${fd.ContentType}

"$
            Log($"1. s_1=${s_1}"$)
            b_1 = s_1.Replace(CRLF, eol_1).GetBytes("UTF8")
            str_1.WriteBytes(b_1, 0, b_1.Length)
            Dim ins As InputStream = File.OpenInput(fd.Dir, fd.FileName)
            File.Copy2(ins, str_1)
        Next
    End If
    empty_1 = MultipartStartSection (str_1, empty_1)
    Log("3.Empty_1=" & empty_1)
    s_1 = _
$"--${boundary_1}--
"$
    Log($"1. s_1=${s_1}"$)
    b_1 = s_1.Replace(CRLF, eol_1).GetBytes("UTF8")
    str_1.WriteBytes(b_1, 0, b_1.Length)
    Dim job1_1 As HttpJob
    job1_1.Initialize("", Me)
    str_1.Close
    Dim length_1 As Int = File.Size(xui.DefaultFolder, TempFileName_1)
    Dim stin_1 As InputStream = File.OpenInput(xui.DefaultFolder, TempFileName_1)
    Dim cin_1 As CountingInputStream
    cin_1.Initialize(stin_1)
    Dim req_1 As OkHttpRequest = job1_1.GetRequest
    req_1.InitializePost(sURL, cin_1, length_1)
    req_1.SetContentType("multipart/form-data; boundary=" & boundary_1)
    req_1.SetContentEncoding("UTF8")
    TrackProgress(cin_1, length_1)
    job1_1.Tag = TempFileName_1
    CallSubDelayed2(HttpUtils2Service, "SubmitJob", job1_1)
    'Log(job1_1)
    Log("=================================================================================")
    Return job1_1
End Sub

Private Sub MultipartStartSection (stream_1 As OutputStream, empty_1 As Boolean) As Boolean
    If empty_1 = False Then
        stream_1.WriteBytes(Array As Byte(13, 10), 0, 2)
    Else
        empty_1 = False
    End If
    Return empty_1
End Sub

Private Sub TrackProgress (cin_1 As CountingInputStream, length_1 As Int)
    TrackerIndex = TrackerIndex + 1
    Dim MyIndex_1 As Int = TrackerIndex
    Do While MyIndex_1 = TrackerIndex
        Log($"$1.2{cin_1.Count * 100 / length_1}%"$)
        If cin_1.Count = length_1 Then Exit
        Sleep(100)
    Loop
End Sub
 
Upvote 0

hatzisn

Well-Known Member
Licensed User
Longtime User
Actually I think he meant something like "dim _MyVariable1 as int" as opposed to "dim MyVariable_1 as int"

I did try it but the result was an error so I was forced to put it in the end... In java it is possible I believe but not in B4J...
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
try a search about obfuscating variable names...
I found this, might be of interest
 
Upvote 0

hatzisn

Well-Known Member
Licensed User
Longtime User
No need to use CreateMultipartJob.

Use Job.PostMultipart.

If it still doesn't work then post the updated code and the logs.

Thanks for your response. Ok, I have done this. Here are the logs and the new code follows bellow. The result is exactly the same.

The response from debug is this:
Waiting for debugger to connect...
Program started.
1
2
{"success":true}

The response from release and release obfuscated is this:


An other conclusion is it does not depend on the file size. The same is valid for a ~200K file and the same is valid for a ~2.5MB file.

Here is the code:

B4X:
Public Sub GetTheResponse(assr_1 As String, Directory_1 As String, Filename_1 As String, ActCase_1 As Boolean)
 
    'The following two are global variables
    TempCounter = 0
    TrackerIndex = 0
 
    Dim fd As MultipartFileData
    fd.Initialize
    fd.KeyName = "file"
    fd.Dir = Directory_1
    fd.FileName = Filename_1
 
    Dim NameValues As Map
    NameValues.Initialize
    NameValues.Put("value1", "tp1resp")
    NameValues.Put("assurance", assr_1)
 
    Dim sURL As String
    Select Case ActCase_1
        Case False
            sURL = "https://api.myserver.com/getdata1"
        Case True
            sURL = "https://api.myserver.com/getdata2"
    End Select
 
    Dim job As HttpJob        '= CreateMultipartJob(sURL, NameValues, Array(fd))
    job.Initialize("",Me)
    job.PostMultipart(sURL, NameValues, Array(fd))
    job.GetRequest.SetHeader("Authorization", $"Bearer 12312414ghv1c24h122421h3c1hc4g1h4g2214"$)
    Log("1")
    Wait For (job) JobDone (job As HttpJob)
    Log("2")
    'Log(job)
    Log(job.GetString)
    'File.Delete(xui.DefaultFolder, job.Tag)
    job.Release
End Sub
 
Upvote 0

hatzisn

Well-Known Member
Licensed User
Longtime User
Thank you it works...
 
Upvote 0
Top