Android Tutorial Android Http Multipart requests

Status
Not open for further replies.
For new projects it is recommended to use OkHttpUtils2: https://www.b4x.com/android/forum/threads/54723/#content

Multipart POST requests are usually used by Html Form components to upload files and pairs of name/values to the server.
The attached code module makes it easy to create such requests.

The following code demonstrates the usage of this code module:
B4X:
Sub Process_Globals
    Dim hc As HttpClient
End Sub

Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        hc.Initialize("hc")
    End If
    'Add files
    Dim files As List
    files.Initialize
    Dim FD As FileData
    fd.Initialize
    fd.Dir = File.DirRootExternal
    fd.FileName = "temp.apk"
    fd.KeyName = "upfile2"
    fd.ContentType = "application/octet-stream"
    files.Add(fd)
    'Add second file
    Dim fd As FileData
    fd.Initialize
    fd.Dir = File.DirAssets
    fd.FileName = "1.png"
    fd.KeyName = "upfile"
    fd.ContentType = "application/octet-stream"
    files.Add(fd)
    'Add name / values pairs (parameters)
    Dim NV As Map
    NV.Initialize
    NV.Put("note1", "abc")
    NV.Put("note2", "def")
    Dim req As HttpRequest
    req = MultipartPost.CreatePostRequest("http://www.example.com/1.php", NV, files)
    hc.Execute(req, 1)
End Sub
Sub hc_ResponseError (Response As HttpResponse, Reason As String, StatusCode As Int, TaskId As Int)
    Log("error: " & Response & " " & StatusCode)
    If response <> Null Then
        Log(Response.GetString("UTF8"))
        Response.Release
    End If
End Sub
Sub hc_ResponseSuccess (Response As HttpResponse, TaskId As Int)
    Msgbox(Response.GetString("UTF8"), "")
    Response.Release
End Sub
The method MultipartPost.CreatePostRequest does most of the job.
It accepts three parameters. The first is the URL (of the target, not the html page).
The second is a Map that contains the names and values pairs that will be sent to the server.
You can pass Null if it is not needed.
The third parameter is a List that holds FileData items.
Each FileData item represents a file that will be uploaded to the server.
Again, you can pass Null if it is not needed.
For example:
B4X:
    Dim fd As FileData
    fd.Initialize
    fd.Dir = File.DirAssets
    fd.FileName = "1.png"
    fd.KeyName = "upfile"
    fd.ContentType = "application/octet-stream"
The above code will upload a file named 1.png from the assets folder (Files tab). The file will be mapped to "upfile" key.
 

Attachments

  • MultipartPost.bas
    2 KB · Views: 1,833
Last edited:

RjCl

Member
Licensed User
Longtime User
So, how would get the text response from the code in your first post which I'm using to upload a single file and its working great. Just need to get text response from server?
 

RjCl

Member
Licensed User
Longtime User
Thanks,

But please could you show how to use Response.GetAsynchronously for getting reply from a PHP script that one may have used in this tutorial, and to help others who are not aware of Response.GetString as its not mentioned in the first post?
 

cstangor

Member
Licensed User
Longtime User
Hello, I'm trying to use this routine in B4J but I cannot make it work. Is there an alternative? Thanks
 

cstangor

Member
Licensed User
Longtime User
B4X:
'Add name / values pairs (parameters)
    Dim NV As Map
    NV.Initialize
    NV.Put("note1", "abc")
    NV.Put("AWSAccessKeyId", "AKIAJBQ7MOX3B5WFZGBA")
    NV.Put("Signature", "Mt9rDE3PTA6tVulatxIFgKC9qjM")
    NV.Put("Filename", "testfile")
    NV.Put("key", "account_120000000081466/attachments/32539392/testfile")
    NV.Put("acl", "Private")
    NV.Put("success_action_redirect", "https://umd.instructure.com/api/v1/files/32539392/create_success")
   
    Dim fd As FileData
    fd.Initialize
    fd.Dir = File.DirApp
    fd.FileName = "json.txt"
    fd.KeyName = "file"
    fd.ContentType = "application/octet-stream"
    Dim fl As List: fl.initialize
    fl.Add(fd)

    Dim req As HttpRequest = CreatePostRequest("https://instructure-uploads.s3.amazonaws.com", NV, fl)
    hc.Execute(req, 1)
What is not working? It should work with B4J as well.

I get a null pointer exception when I call the httprequest.
 

cstangor

Member
Licensed User
Longtime User
Program started.
java.lang.NullPointerException
at anywheresoftware.b4a.http.HttpClientWrapper.executeWithTimeout(HttpClientWrapper.java:310)
at anywheresoftware.b4a.http.HttpClientWrapper.access$0(HttpClientWrapper.java:308)
at anywheresoftware.b4a.http.HttpClientWrapper$ExecuteHelper.run(HttpClientWrapper.java:207)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)

Can you post the full error message from the logs?
 

Nickelgrass

Active Member
Licensed User
Longtime User
Hello!

Ive successfully implemented this, thanks a lot!
It works, in my App I am uploading a zip file to a server vie php.

I just nocitced one severe problem. I wanted to check the file size sent with the one the server stored. The strange thing is they have a difference of 2 bytes. I mean the actual bytes not the size on disk. It seems the file on the android device is 2 bytes smaller than the one on the server (Xampp on windows).
I then had my php script calculate the md5 checksum and compared it with the one the ESFileExplorer generated of the file on the Android device. They were completely different.
How can that be? It extracts correctly.
Thanks!
Regards
 

Nickelgrass

Active Member
Licensed User
Longtime User
Thanks for the reply, at the end of the upladed file there is a newline "&h0D &h0A". Is there any way of solving this without rewriting the file on the server with those croped, that would be a bit mucky? Ive looked at the Multipartpost.bas but couldn't see why it does include those two characters. How can I tell the server how long that file is?

EDIT: found it sniffing the corespondence. It seems there was an extra EOL ind the MultiPartPost.bas that was one to many in lines 37 and 38. Commented these line and it worked like a charm.
 
Last edited:

wmardian

Member
Licensed User
Longtime User
Multipart POST requests are usually used by Html Form components to upload files and pairs of name/values to the server.
The attached code module makes it easy to create such requests.

The following code demonstrates the usage of this code module:
B4X:
Sub Process_Globals
    Dim hc As HttpClient
End Sub

Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        hc.Initialize("hc")
    End If
    'Add files
    Dim files As List
    files.Initialize
    Dim FD As FileData
    fd.Initialize
    fd.Dir = File.DirRootExternal
    fd.FileName = "temp.apk"
    fd.KeyName = "upfile2"
    fd.ContentType = "application/octet-stream"
    files.Add(fd)
    'Add second file
    Dim fd As FileData
    fd.Initialize
    fd.Dir = File.DirAssets
    fd.FileName = "1.png"
    fd.KeyName = "upfile"
    fd.ContentType = "application/octet-stream"
    files.Add(fd)
    'Add name / values pairs (parameters)
    Dim NV As Map
    NV.Initialize
    NV.Put("note1", "abc")
    NV.Put("note2", "def")
    Dim req As HttpRequest
    req = MultipartPost.CreatePostRequest("http://www.example.com/1.php", NV, files)
    hc.Execute(req, 1)
End Sub
Sub hc_ResponseError (Response As HttpResponse, Reason As String, StatusCode As Int, TaskId As Int)
    Log("error: " & Response & " " & StatusCode)
    If response <> Null Then
        Log(Response.GetString("UTF8"))
        Response.Release
    End If
End Sub
Sub hc_ResponseSuccess (Response As HttpResponse, TaskId As Int)
    Msgbox(Response.GetString("UTF8"), "")
    Response.Release
End Sub
The method MultipartPost.CreatePostRequest does most of the job.
It accepts three parameters. The first is the URL (of the target, not the html page).
The second is a Map that contains the names and values pairs that will be sent to the server.
You can pass Null if it is not needed.
The third parameter is a List that holds FileData items.
Each FileData item represents a file that will be uploaded to the server.
Again, you can pass Null if it is not needed.
For example:
B4X:
    Dim fd As FileData
    fd.Initialize
    fd.Dir = File.DirAssets
    fd.FileName = "1.png"
    fd.KeyName = "upfile"
    fd.ContentType = "application/octet-stream"
The above code will upload a file named 1.png from the assets folder (Files tab). The file will be mapped to "upfile" key.
Dear Erel,
Could you please help us, what is the php file should be?
I already read and use the code from php.net to handle file upload but i can find uploaded file in the server..

Thanks in advance
Best Regards
 

Douglas Farias

Expert
Licensed User
Longtime User
B4X:
        Dim files As List
        files.Initialize
        Dim fd As FileData
        fd.Initialize
        fd.Dir = fp
        fd.FileName = "camera.jpg"
        fd.KeyName = "Original"
        fd.ContentType = "application/octet-stream"
        files.Add(fd)
        Dim NV As Map
        NV.Initialize
        NV.Put("data" ,"Data=Caller:Save;UserID:"&userid&";Type:0")
        Dim req As HttpRequest
        req = MultipartPost.CreatePostRequest("http://mysite.com/ws/photo/", NV, files)
        hc.Execute(req, 1)

i use this, i have try with http2utils post file but not sucess!
sometimes i need upload 2 images too

have a way to know the progress for multipartpost?
 
Last edited:
Status
Not open for further replies.
Top