Android Question Download image

Emme Developer

Well-Known Member
Licensed User
Longtime User
Hi all!
i'm trying to download an image from a server and a string, by using a php file. I want to avoid to use base64 encode and decode. This is my php code


B4X:
<?php
define ('SITE_ROOT', realpath(dirname(__FILE__)));

$target_dir = SITE_ROOT . "/user_images/";
$target_file = $target_dir . basename($_GET["name"]);
$target_cache = substr_replace($target_file , 'cache', strrpos($target_file , '.') +1);

if (file_exists($target_cache)) {
    $myfile = fopen($target_cache, "r") or die("Unable to open file!");
    $boh = fgets($myfile);
    if ($boh !== $_GET["cache"]) {
        //echo $boh;
        header("Content-disposition: attachment; filename=\"$target_file\"");
        header('Content-transfer-encoding: binary');
        header('Content-type: image/jpg');
        echo file_get_contents($target_file);
    }
} else {
    echo "The file $target_cache does not exist";
}
?>

And this is my code to download, but i get Error in bitmap. Some advices?

B4X:
Dim j As HttpJob
    j.Initialize("",Me)
    j.Download2("www.site.com/try.php",Array As String("name",name,"cache",cache))
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        Log(j.GetString)
        Dim bmp As Bitmap = j.GetBitmap 'error
...
....
...
 

ilan

Expert
Licensed User
Longtime User
Why not download directly the image or string without using php?

(I am no server specialist this is why i ask. I would just use httpjob to download directly the image and string)
 
Upvote 0

Emme Developer

Well-Known Member
Licensed User
Longtime User
Why not download directly the image or string without using php?

(I am no server specialist this is why i ask. I would just use httpjob to download directly the image and string)
Because i want to download an image only if cache parameter passed is the expected. I solved my problem by editing header (header("Content-Type: application/force-download")) and it works, but to sync also the cache file i need to send also the string. This give me an error. I tried to do this to avoid 2 requests at server, but i don't think i can do in this way..
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
One issue I see (just looking at code, not running/testing anything) is that if your cache string matches (in other words
B4X:
if ($boh !== $_GET["cache"])
evaluates to false), you return nothing from your PHP script. This should still result in
B4X:
If j.Success
to evaluate to true and then you are loading at bitmap (via
B4X:
Dim bmp As Bitmap = j.GetBitmap
) from nothing.
 
Upvote 0

Emme Developer

Well-Known Member
Licensed User
Longtime User
One issue I see (just looking at code, not running/testing anything) is that if your cache string matches (in other words
B4X:
if ($boh !== $_GET["cache"])
evaluates to false), you return nothing from your PHP script. This should still result in
B4X:
If j.Success
to evaluate to true and then you are loading at bitmap (via
B4X:
Dim bmp As Bitmap = j.GetBitmap
) from nothing.
What i want to achieve is this. If hash code (cache) is the same on device and server, then i don't download the image (because it is already on device). If it's different (upload php change hash key when a new image is uploaded) the i download the image and the hash key
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Understood. But if the hash matches, you'll still get a True for j.Success and then you are loading a bitmap (j.GetBitmap) from an empty page. This may (not tested) cause an error. Please note I'm guessing a tad here since you did not post the error message, nor when it happens (for cache matches? for cache mismatch? for both?) and you just pointed out that j.GetBitmap is causing you some issues (at least that's what I'm getting from the 'error tag).
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
} else {
echo "The file $target_cache does not exist";
}
Even this will result in a j.Success being True and then you would load that string as a bitmap.
 
Upvote 0

Emme Developer

Well-Known Member
Licensed User
Longtime User
Understood. But if the hash matches, you'll still get a True for j.Success and then you are loading a bitmap (j.GetBitmap) from an empty page. This may (not tested) cause an error. Please note I'm guessing a tad here since you did not post the error message, nor when it happens (for cache matches? for cache mismatch? for both?) and you just pointed out that j.GetBitmap is causing you some issues (at least that's what I'm getting from the 'error tag).
Error is "Error to load bitmap", so i used a try to catch this error. If there is an error, this means that i have the image in cache. If not, so i need to display and save the new image
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
this means that i have the image in cache
That is one meaning, but it could also mean "The file $target_cache does not exist". So if you need to discern between the two cases (cache hit and file does not exist), then catch/try alone will not do it. If it does not matter, then catch/try should be ok. You could also use PHP's http_response_code to return a non 200 response (http://php.net/http-response-code) and make j.Success false. Then you can test for an empty return string (equals cache hit) or whatever message you would like to return (from your PHP script).
 
Upvote 0

Emme Developer

Well-Known Member
Licensed User
Longtime User
That is one meaning, but it could also mean "The file $target_cache does not exist". So if you need to discern between the two cases (cache hit and file does not exist), then catch/try alone will not do it. If it does not matter, then catch/try should be ok. You could also use PHP's http_response_code to return a non 200 response (http://php.net/http-response-code) and make j.Success false. Then you can test for an empty return string (equals cache hit) or whatever message you would like to return (from your PHP script).
Many thanks for your help, i will improve the logic of my code
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
How about checking the date of the image when it was uploaded and if there is a newer file then download. Like this u just need to check 1 file without checking the hash code.

I do it in one of my b4a apps to check if a newer file exist in my server then on my device and if yes i download and replace the old one. I do it with php.

Do u need the code?
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
How about checking the date of the image
without checking the hash code.
Hash can overcome the issues with time configuration, where both the server and the client have to have the same time or be aware of each others time difference (I'm considering file timestamps, not timestamps within any "meta" information of a picture). A hash would circumvent time issues. Of course I may be overthinking this (a very good possibility). You should have had this bright idea at the thread where @Emme Developer was asking for suggestions (here) :);):D
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
ok i will post my code and everyone can use it if it suits their needs.

PHP:

B4X:
<?php
date_default_timezone_set('Asia/Jerusalem'); // CDT
$return_array = array();

if ($handle = opendir('.')) {


    while (false !== ($file = readdir($handle))) {
        if($file == "." or $file == "..")
        {
        }
        else
        {
            $return_array[] = $file  . "|" . date ("d-m-Y|H:i:s", filemtime($file));
        }
    }
    echo json_encode($return_array);
    closedir($handle);
}
?>

b4a:

B4X:
Sub checkfileTime
      Dim fi As HttpJob
    fi.Initialize("getfiles", Me)
    fi.Download2(changedftp  & "/lists/files.php", Array As String("Null", "Null"))
End Sub

'....
Case "getfiles"       
    res = job.GetString
    Dim parser As JSONParser
    parser.Initialize(res)

    Dim ListOfFiles As List
    ListOfFiles = parser.NextArray
    Log(ListOfFiles.Size)
     
    If ListOfFiles.Size > 0 Then
      For i = 0 To ListOfFiles.Size - 1
          Log(">> File: " & ListOfFiles.Get(i))
       
          Dim str() As String = Regex.Split("\|",ListOfFiles.Get(i))
          Dim mynr As String = str(0)
          mynr = mynr.Replace(".txt","")
       
          If mynr = LineNumber Then
       
              Dim date As String = str(1)
              Dim time As String = str(2)
           
              date = date.Replace("-","/")
              DateTime.DateFormat = "dd/MM/yyyy"
           
              Log("test date: " & date & "|" & time)

              Dim newdate As Long = DateTime.DateTimeParse(date,time)
           
              'newdate = newdate + (DateTime.TicksPerHour * 2)'new server
              Log(DateTime.date(newdate) & "|" & DateTime.time(newdate))

              Dim olddate As Long = File.LastModified(File.DirInternal,LineNumber & ".txt")
              Log("olddate: " & DateTime.date(olddate) & "|" & DateTime.time(olddate))
           
              If newdate > olddate Then updatedownload
 
          Exit
          End If
      Next
    End If
 
Upvote 0
Top