B4J Tutorial Easy upload files with httputils' original poststring to a php script with x parameters

KMatle

Expert
Licensed User
The normal postfile method just posts the file data. So you are not able to get the filename and other needed parameters. There are other examples, but sometimes you need a small solution. The code is for B4A, too but I did not test it with huge files on a phone/tablet.

- read the file into a bytearray with RAF
- Base64 encode it into a string
- fill ServerFolderName and ServerFileName
- use the JSON generator
- all is put to a JSON string (JSONRow)
- the JSONRow ist put in a List (JSONList)
- generate it to a string (so you transfer ONE string only)
- use the poststring-method to transfer it to the php

Note: This is not needed but I reuse the JSON code here even if I just transfer 1 Map. By adding more or less rows, the code does not change. Only in php I must get the vars.

In php the string is retrieved and converted back to a JSON List and from this to a row. Normally I have a loop to get all rows. Here I only need one row with the data (=0)

From the row the vars are retrieved by name (like in B4x with map.get("xxx")). The file is converted back from Base64 and written in the given folder with the given filename.

B4X:
<?php

   $jsonstring = file_get_contents("php://input");
  
   $jsonlist = array();
   $jsonrow = array();
   $jsonlist=json_decode($jsonstring, true);
   
   $jsonrow=$jsonlist[0];

    $ServerFolderName=$jsonrow["ServerFolderName"];
     $ServerFileName=$jsonrow["ServerFileName"];
    $FileContent=base64_decode($jsonrow["FileContent"]);
       
 
   file_put_contents($ServerFolderName . $ServerFileName, $FileContent);
?>
B4X:
    Dim upl As RandomAccessFile
    Dim l As Int
    Dim ServerFolderName, ServerFileName As String
    upl.Initialize(File.DirApp &"\localfolder\","localfilename.xxx", False)
   
    l = upl.Size
    Log("Länge: " & l)
    Dim FileBuffer(l) As Byte, fileString As String
    upl.ReadBytes(FileBuffer,0,l,upl.CurrentPosition)
    upl.Close
   
    Dim su As StringUtils
    fileString=su.EncodeBase64(FileBuffer)
   
    ServerFileName="ServerFileName.xxx"
    ServerFolderName="ServerFolder/Subfolder/"
   
    JsonList.Initialize
    JsonRowMap.Initialize
   
    JsonRowMap.put("FileContent", fileString)
    JsonRowMap.put("ServerFolderName", ServerFolderName )
    JsonRowMap.put("ServerFileName", ServerFileName)
   
    JsonList.add(JsonRowMap)
  
    Dim JSONGenerator As JSONGenerator
    JSONGenerator.Initialize2(JsonList)
  
    Dim JSONstring As String
    JSONstring = JSONGenerator.ToString
   
    Dim FileUpload As HttpJob
         FileUpload.Initialize("FileUpload", Me)
        FileUpload.PostString("http://192.168.178.21/phpfolder/FileUpload.php",JSONstring)
Multi-File upload? No problem. Just call it n-times... You could put a loop arround it but this may cause problems due to the length of the string.
 

Ahmad-Ng

Member
Licensed User
GREAT assistance to anyone facing the frustration of uploading to a website!! More than a year later it has been a saving grace for a project I am handling!!!
 

tufanv

Expert
Licensed User
The normal postfile method just posts the file data. So you are not able to get the filename and other needed parameters. There are other examples, but sometimes you need a small solution. The code is for B4A, too but I did not test it with huge files on a phone/tablet.

- read the file into a bytearray with RAF
- Base64 encode it into a string
- fill ServerFolderName and ServerFileName
- use the JSON generator
- all is put to a JSON string (JSONRow)
- the JSONRow ist put in a List (JSONList)
- generate it to a string (so you transfer ONE string only)
- use the poststring-method to transfer it to the php

Note: This is not needed but I reuse the JSON code here even if I just transfer 1 Map. By adding more or less rows, the code does not change. Only in php I must get the vars.

In php the string is retrieved and converted back to a JSON List and from this to a row. Normally I have a loop to get all rows. Here I only need one row with the data (=0)

From the row the vars are retrieved by name (like in B4x with map.get("xxx")). The file is converted back from Base64 and written in the given folder with the given filename.

B4X:
<?php

   $jsonstring = file_get_contents("php://input");
 
   $jsonlist = array();
   $jsonrow = array();
   $jsonlist=json_decode($jsonstring, true);
 
   $jsonrow=$jsonlist[0];

    $ServerFolderName=$jsonrow["ServerFolderName"];
     $ServerFileName=$jsonrow["ServerFileName"];
    $FileContent=base64_decode($jsonrow["FileContent"]);
     
 
   file_put_contents($ServerFolderName . $ServerFileName, $FileContent);
?>
B4X:
    Dim upl As RandomAccessFile
    Dim l As Int
    Dim ServerFolderName, ServerFileName As String
    upl.Initialize(File.DirApp &"\localfolder\","localfilename.xxx", False)
 
    l = upl.Size
    Log("Länge: " & l)
    Dim FileBuffer(l) As Byte, fileString As String
    upl.ReadBytes(FileBuffer,0,l,upl.CurrentPosition)
    upl.Close
 
    Dim su As StringUtils
    fileString=su.EncodeBase64(FileBuffer)
 
    ServerFileName="ServerFileName.xxx"
    ServerFolderName="ServerFolder/Subfolder/"
 
    JsonList.Initialize
    JsonRowMap.Initialize
 
    JsonRowMap.put("FileContent", fileString)
    JsonRowMap.put("ServerFolderName", ServerFolderName )
    JsonRowMap.put("ServerFileName", ServerFileName)
 
    JsonList.add(JsonRowMap)
 
    Dim JSONGenerator As JSONGenerator
    JSONGenerator.Initialize2(JsonList)
 
    Dim JSONstring As String
    JSONstring = JSONGenerator.ToString
 
    Dim FileUpload As HttpJob
         FileUpload.Initialize("FileUpload", Me)
        FileUpload.PostString("http://192.168.178.21/phpfolder/FileUpload.php",JSONstring)
Multi-File upload? No problem. Just call it n-times... You could put a loop arround it but this may cause problems due to the length of the string.
Hello,

I am trying this solution with b4i , I think there is no problem with code for b4i , job returns success but the file is not uploaded in the server.

php code is :

B4X:
<?php

   $jsonstring = file_get_contents("php://input");

   $jsonlist = array();
   $jsonrow = array();
   $jsonlist=json_decode($jsonstring, true);

   $jsonrow=$jsonlist[0];

    $ServerFolderName=$jsonrow["ServerFolderName"];
     $ServerFileName=$jsonrow["ServerFileName"];
    $FileContent=base64_decode($jsonrow["FileContent"]);


   file_put_contents($ServerFolderName . $ServerFileName, $FileContent);
?>
b4i code is:

B4X:
Sub upload
Dim upl As RandomAccessFile
    Dim l As Int
    Dim ServerFolderName, ServerFileName As String
    upl.Initialize(File.DirDocuments ,"tufan.m4a", False)
 
    l = upl.Size
    Log("Länge: " & l)
    Dim FileBuffer(l) As Byte, fileString As String
    upl.ReadBytes(FileBuffer,0,l,upl.CurrentPosition)
    upl.Close
 
    Dim su As StringUtils
    fileString=su.EncodeBase64(FileBuffer)
 
    ServerFileName="tufan.m4a"
    ServerFolderName="test/"
 
    jsonlist.Initialize
    jsonrowmap.Initialize
 
    jsonrowmap.put("FileContent", fileString)
    jsonrowmap.put("ServerFolderName", ServerFolderName )
    jsonrowmap.put("ServerFileName", ServerFileName)
 
    jsonlist.add(jsonrowmap)
 
    Dim JSONGenerator As JSONGenerator
    JSONGenerator.Initialize2(jsonlist)
 
    Dim JSONstring As String
    JSONstring = JSONGenerator.ToString
 
    Dim FileUpload As HttpJob
         FileUpload.Initialize("FileUpload", Me)
        FileUpload.PostString("https://server/FileUpload.php",JSONstring)
   
        File

End Sub
Sub JobDone (Job As HttpJob)
Log("JobName = " & Job.JobName & ", Success = " & Job.Success)
If Job.JobName="FileUpload" Then
Log(Job.Success)
    End If
End Sub
job returns true but file is not there:

B4X:
Länge: 83430
JobName = FileUpload, Success = true
any idea ? thx
 

KMatle

Expert
Licensed User
Hard to say. The php code is very simple and should work without any problems. I assume there's a problem with the folder or file name. For a test set the names hardcoded in the php script.
 
Top