PHP script displayed blob image executed twice?

I could not find a brief way to summarize the question in the title, let me clarify:

I have a website that uses the PHP script "getImg.php", which takes an image binary from my database and displays it when invoked with the HTML img tag on a separate page.

I would like to record the number of views by people, so I added a simple line to increase the "views" property for the corresponding image.

I thought it would be simple, but it turns out that it is increasing twice. My trivial way around this was to make the “views” column float and increase by 0.5 to get in step 1. However, I looked through my database today to find 0.5 on some images!

When I comment on the end of the print, it works correctly. I assumed that the call from the HTML tag plus the script itself is counted for two calls? But this is not like other people.

Is this just my setup?

<?php # Connect to db include('db.php'); # Get ID $id = $_GET['id']; if(!is_numeric($id)) exit; $q = $db->prepare("SELECT tNail,image,format FROM gallery WHERE id = '$id'"); $q->execute(); $row = $q->fetch(PDO::FETCH_ASSOC); if(array_key_exists("thumb", $_GET)) $img = base64_decode($row["tNail"]); else { $img = base64_decode($row["image"]); # Add to views if not thumb // 0.5 because script called twice due to print? $db->query("UPDATE gallery SET views = (views + 0.5) WHERE id = '$id'"); } switch($row["format"]) { case ".jpg": header("Content-type: image/jpeg"); break; case ".png": header("Content-type: image/png"); break; } print $img; ?> 

Thanks for any help.

+4
source share
2 answers

This seems to be a more complicated problem. Browsers, such as Chrome, can preload images so that they are downloaded once, and if the user clicks on the link to the image, it is downloaded twice.

Check

Download the image to your browser and then check your apache access.log, and if you see 2 requests at the same time, this is a problem with the browser.

+3
source

Here is your problem:

 if(array_key_exists("thumb", $_GET)) $img = base64_decode($row["tNail"]); else {$img = base64_decode($row["image"]);//<== 

You start this if...else branch as a one-line deal, but in the other case, you execute a block of code. Running php does 1 line below if it skips the else and the first subsequent line and continues, as if the closing barque were not there. This is some kind of mistake that I think of. Recently, I have heard many people complaining about this. (since 5.3.7 or something else). Set your ini report E_STRICT and check it doesn't matter


It seems that Besnik found him before I even started looking into him (well done and +1). @Lee: Here's how to avoid this problem:

 RewriteEngine On SetEnvIfNoCase X-Forwarded-For .+ proxy=yes SetEnvIfNoCase X-moz prefetch no_access=yes # block pre-fetch requests with X-moz headers RewriteCond %{ENV:no_access} yes RewriteRule .* - [F,L] 

Found here


 if(array_key_exists("thumb", $_GET)) { $img = base64_decode($row["tNail"]); } else { $img = base64_decode($row["image"]); $db->query("UPDATE gallery SET views = (views + 0.5) WHERE id = '$id'"); } 

If any of the branches are missing curly braces that may cause problems. Again: if the if statement is not contained in the code block, only the first statement (all the code before the first half-colony) following the else statement will be interpreted as a branch. This is the purpose of the $img variable in your case. In both cases, database insertion will be called.

You can check the weather or not execute the db request with __halt_compiler :

 if(array_key_exists("thumb", $_GET)) { $img = base64_decode($row["tNail"]); } else { $img = base64_decode($row["image"]); if ($db->query("UPDATE gallery SET views = (views + 0.5) WHERE id = '$id'")) { if (array_key_exists("thumb", $_GET)) {//this should be an impossible branch __halt_compiler();//or exit || throw if this is a (member) function } } } 

The __halt_compiler() function cannot be used in any other area except the global namespace, and affects only the current script being executed, if this script is an inclusion, for example, index.php , index.php will continue as is, but the inclusion of the script will be stopped. Read the docs for a more complete explanation (I suck an explanation of things).


All this will not help you avoid this problem when calculating this feature, so I suggest this problem with inappropriate work:

 if(array_key_exists("thumb", $_GET)) { $img = base64_decode($row["tNail"]); $db = null;//disconnect } else { $img = base64_decode($row["image"]); if ($db !== null) {//or $db instanceof PDO (or whatever object you're using) //or try{$db->query('UPDATE...');}catch(Exception $e){}//<- suppress exception $db->query("UPDATE gallery SET views = (views + 0.5) WHERE id = '$id'"); } } 

Let me know which of these works, or if you are still facing the same problem. I find this very curious and therefore interesting :)

+2
source

All Articles