Android Question Help!!! PostMultipart Video Files to server using WaitFor and Php

Mashiane

Expert
Licensed User
Longtime User
Hi there..

I'm trying to no avail to use PostMultipart to upload video files to the server. This works well for my images, but now for my mp4 files at all, these are not fully uploaded. I'm calling this from a class...

B4X:
Sub UploadFilePhp(frm As Object, pQuery As Map, dir As String, fil As String, JobName As String, phpFile As String, phpTag As String)
    CallSub(frm,"ShowSpinner")
    Dim job As HttpJob
    Dim fd As MultipartFileData
    ' initialize the job
    job.Initialize(JobName, frm)
    job.Tag = phpTag
    ' initialize the mulipart
    fd.Initialize
    fd.KeyName = "processfile"
    fd.Dir = dir
    fd.FileName = fil
    ' determine the contenttype
    If fil.EndsWith(".png") = True Then
        fd.ContentType = "image/png"
    else If fil.EndsWith(".gif") = True Then
        fd.ContentType = "image/gif"
    else If fil.EndsWith(".jpg") = True Then
        fd.ContentType = "image/jpeg"
    else If fil.EndsWith(".jpeg") = True Then
        fd.ContentType = "image/jpeg"
    else If fil.EndsWith(".json") = True Then
        fd.ContentType = "application/json"
    else if fil.EndsWith(".pdf") = True Then
        fd.ContentType = "application/pdf"
    else if fil.EndsWith(".mp4") = True Then
        fd.ContentType = "video/mp4"
    Else
        fd.ContentType = "application/octet-stream"
    End If
    ' execute the script to upload the file
    job.PostMultipart(Starter.phpPath & phpFile, pQuery, Array(fd))
    Wait For(job) JobDone(job As HttpJob)
End Sub

And I call this using..

B4X:
dbAction.Initialize
        dbAction.Put("action", "upload")
        dbAction.Put("filepath", "")
        Starter.httpjobs.UploadFilePhp(Me,dbAction,File.Combine(File.DirRootExternal,"Videos"), filename, _
    "upload", "uploadfile.php", "upload")

The PHP file is...

B4X:
<?php
if (isset($_REQUEST['action'])){$action=trim($_REQUEST['action']);} else {$action="";}
if (isset($_REQUEST['filepath'])){$filepath=trim($_REQUEST['filepath']);} else {$filepath="";}

switch ($action)
{
    case "upload":
        $filepath = $filepath . basename( $_FILES['processfile']['name']);
        if(move_uploaded_file($_FILES['processfile']['tmp_name'], $filepath)) {
                echo "success";
            } else{
                echo "fail";
            }
}
?>

My JobDone returns a "success" on upload of the file but then the filesize on the server is not the same as the original file and when ftp(ed) back the mp4 file does not play. The php configuration accepts 20MB file sizes and my file is 12MB.

Is there another way I can do this please. Thanks
 
Last edited:

OliverA

Expert
Licensed User
Longtime User
I'm guessing here, but the difference could be the duration of the upload. Since the MP4's are so much larger than the other files, you may be experiencing some sort of time out issue. It is strange that you still get a success status and therefore I'm guessing that things may go wrong on the PHP side. Looking at this stackoverflow question, the function call set_time_limit(0) may solve your issue (mentioned in one of the comments in this answer). Another suggestion in the stackoverflow question is to modify a couple of settings in the php.ini file: max_execution_time and max_input_time.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
This means that the binary data is encoded as a base 64 string. The actual size will be about 33% larger
I was thinking of that too, but 33% larger 12MB file should still fall under 20MB and therefore I was leaning towards a timeout issue. Would still be interesting to see what happens if the accepted upload size is increased (to something ridiculous, just for testing purposes).

another method besides PostMultipart
Could use the PostByte method, but I don't know if PHP can handle it (B4J's server implementation can :)). Please note that you would need to encode any other info (file name, type, etc. anything you deem necessary) yourself (in the URL perhaps).

Just for kicks, why don't you change
B4X:
else if fil.EndsWith(".mp4") = True Then
        fd.ContentType = "video/mp4"
to
B4X:
else if fil.EndsWith(".mp4") = True Then
        fd.ContentType ="image/jpeg"
just to rule out some configuration issue on the server?
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Multipart messages are text messages. This means that the binary data is encoded as a base 64 string. The actual size will be about 33% larger.

Does it work properly with small files?
With normal jpg files, I have been using the same method just passing it the file name and everything has been perfect. With the mp4 video files, things are different. Now that you are indicating that such are text messages, then that makes everything confusing to say the least.

Yes I have tried it with a smaller mp4 file and it does the same...
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
B4X:
else if fil.EndsWith(".mp4") = True Then
        fd.ContentType ="image/jpeg"
just to rule out some configuration issue on the server?
Actually, I would go to the extreme and even change the filename ending to a jpg, ending up with
B4X:
else if fil.EndsWith(".mp4") = True Then
        fd.FileName = $"${fil}.jpg"$
        fd.ContentType ="image/jpeg"

This should take care of any mime-type configuration issue on either client and/or server side.
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Pheew!!! finally, the issue is actually not the code, the code works perfect without having to chop and change it. I had to go back to where my video is sourced from, the AndroidVideoCapture library, looking at the provided code, one of the events is fired before the camera is released and thus before the video file is closed. For now to solve the issue I added a Sleep(5000) call, just for cleanup, not neat but it worked.

B4X:
Sub avc_max_duration_reached(maxdurationreached As Boolean)
    If maxdurationreached = False Then Return
    modMashiane.showspinner(spinner)
    Sleep(5000)
    ' reset the counter
    LockControls(True)
    lblCountDown.Text = vidLen & "s"
    ' get the day being saved
    strDay = Starter.StateManager.getSetting("day")
    ' dfine the format to save the file
    uFile = "user" & uid & strDay
    filename = uFile & ".mp4"
   
    ' close the camera immediately
    Starter.StateManager.SetSetting("picture", filename)
    Starter.StateManager.SetSetting("ufile", uFile)
    ' show the blurred picture
    'modMashiane.getimageoralternative(imgTaken, filename,"nophoto.png")
    modMashiane.GetPNG(btnTakePicture,"photon.png")
    'get the file and process it
    Dim fLoc As String
    fLoc = File.Combine(File.DirRootExternal,"Videos/" & filename)
    If File.Exists("",fLoc) = True Then
        'upload the file to the server
        modMashiane.showspinner(spinner)
        EnableDisable(False)
        filename = Starter.StateManager.getSetting("picture")
        dbAction.Initialize
        dbAction.Put("action", "upload")
        dbAction.Put("filepath", "")
        Starter.httpjobs.uploadfilephp(Me,dbAction,File.Combine(File.DirRootExternal,"Videos"), filename, _
    "upload", "uploadfile.php", "upload")
    Else
        Msgbox(modTGIF.ConnectionError, modTGIF.TrayTitle)
    End If
End Sub
 
Upvote 0
Top