Incrémentation dans une BDD lors de l'affichage d'une image

a marqué ce sujet comme résolu.

Bonsoir, j'ai depuis un certain temps un problème qui m'embête tout particulièrement, j'espère donc pouvoir trouver de l'aide ici.

Mon but:

  • Afficher une image, (Pour mettre ensuite sur des forums par exemple).
  • Dans une base de donnée, incrémenter de 1 à chaque fois que l'image est affiché par un utilisateur.

Ca marche plutot bien, sauf quand on arrive dans des petites images ! La, l'incrément est de +2, totalement incompréhensible !

Mon code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

try
{
    $bdd = new PDO('mysql:host=localhost;dbname=***', '***', '***');
    $bdd->exec("SET CHARACTER SET utf8");
}
catch(Exception $e)
{
    die('Erreur : '.$e->getMessage());
}

header('Content-Type: image/png');
readfile('../uploads/205');

displayImg('205');

function displayImg($value){
    global $bdd;
    $req = $bdd->prepare("UPDATE files SET display = (display+1) WHERE value = :value");
    $req->execute(array('value' => $value));
    $req->closeCursor();
}

Petite image

Grande image

+0 -0

Bonjour,

Comment tu affiches l'image ? Tous les navigateurs affichent deux fois l'image ? Quel est l'url de l'image ?

C'est hors sujet mais je me demande si ce n'est pas plus optimisé de déclarer en utf8 les requêtes à la connexion :

1
2
<?php
$bdd = new PDO('mysql:host=localhost;dbname=***', '***', '***', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));

En effet, je n'avais pas tester sur plusieurs navigateur et le problème vient bien de la.

Sur firefox (Developper edition et normal) ça me fait un +2 sur les petites images. Or, sur IE11 ça ne me le fait pas. Il faudra que je teste sur Chrome pour voir aussi.

[edit] Sur firefox c'est aléatoire, des fois +2, des fois +3 …

+0 -0

C'est peut-être IE qui bug en affichant qu'une fois l'image, tu l'affiches peut-être plusieurs fois selon les pages, la gestion du cache est peut-être mal configuré.

A-312

Si on regarde mon code, je vais sur cette page qui m'affiche donc une seul et unique fois l'image. Et j'ai regarder avec firefox. Même en désactivant le cache, rien ne change.

Bonjour,

Comment tu affiches l'image ? […] Quel est l'url de l'image ?

A-312

Comment tu l'affiches, c'est-à-dire si c'est directement en HTML, ou en JS. Si c'est via l'attribut src d'un élément IMG ou via des règles CSS (background-img).

Regarde aussi l'inspecteur de code de ton navigateur, onglet réseau.

+0 -0

Donc, j'ai ce fichier PHP:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
try
{
    $bdd = new PDO('mysql:host=localhost;dbname=***', '***', '***');
    $bdd->exec("SET CHARACTER SET utf8");
}
catch(Exception $e)
{
    die('Erreur : '.$e->getMessage());
}

header('Content-Type: image/png');
readfile('../uploads/205');

displayImg('205');

function displayImg($value){
    global $bdd;
    $req = $bdd->prepare("UPDATE files SET display = (display+1) WHERE value = :value");
    $req->execute(array('value' => $value));
    $req->closeCursor();
}

Je me rend sur la page. Firefox me sort se code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    <html>
        <head>
            <meta name="viewport" content="width=device-width; height=device-height;"></meta>
            <link rel="stylesheet" href="resource://gre/res/ImageDocument.css"></link>
            <link rel="stylesheet" href="resource://gre/res/TopLevelImageDocument.css"></link>
            <link rel="stylesheet" href="chrome://global/skin/media/TopLevelImageDocument.css"></link>
            <title>essai.php (Image BMP, 37 × 45 pixels)</title>
        </head>
        <body>
            <img src="http://files.***.**/uploads/essai.php" alt="http://files.***.**/uploads/essai.php"></img>
        </body>
    </html>

Et IE me sors ceci:

IE 11

Dans l'onglet réseaux de firefox, rien d'anormal.

Onglet réseau de firefox

Et si j'ajoute l'image sur une autre page, ça fonctionne.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width; initial-scale=1.0;">
    </head>
    <body>
        <img src="http://files.***.**/uploads/essai.php" alt="img"/>
    </body>
</html>

Ok, donc visiblement il y a problème quand Firefox charge le fichier directement.

En parcourant quelques forums j'ai vu que Firefox tentait en fait de charger l'image une deuxième fois pour l'utiliser en tant que favicon (pour l'afficher dans l'onglet), chose qu'il ne fait pas s'image fait plus de 1023 pixels de large.

Le bug officiel (qui date de 2010 au moins) : https://bugzilla.mozilla.org/show_bug.cgi?id=583351

Tu peux essayer de dédoublonner "au plus fin" même si c'est :

sale et hacky

Si t'as deux requêtes dans un laps de temps extrêmement faible, provenant de la même IP, avec le même user-agent (Firefox en l'occurrence) y'a de fortes chances que ce soit un doublon.

C'est pas ce qui se fait de plus propre… Mais bon.

+0 -0

Firefox doit considérer la page comme une page qui affiche une simple image et il souhaite afficher un favicon si il n'y en a pas, en dernier ressort il doit surement prendre celle de la page.

Je ne pense pas que ça soit vraiment à considérer comme un bug, car c'est simple à corriger.

Je viens essayer ton code avec firefox je n'ai aucun soucis (étrange). En solution je te propose (classé par simplicité) :

  • Mettre un favicon à la racine de ton site ou via un meta.
  • Essaye en mettant un paramètre GET dans l'url, et faire ton incrémentation uniquement si tu as ce paramètre.
  • Utilise l'header E-Tag (avec cache-control). Comme ceci :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
session_start();
if (isset($_GET["l"])) {
    $etag = (isset($_SERVER["HTTP_IF_NONE_MATCH"])) ? $_SERVER["HTTP_IF_NONE_MATCH"] : 12;
    header("Cache-Control: max-age=1200, public"); //1200 secondes -> 20 minutes
    header("ETag: " + $etag);

    if (isset($_SERVER["HTTP_IF_NONE_MATCH"])) { //Deja vue ou moins de 20 minutes
        header("HTTP/1.1 304 Not Modified"); //On ne renvois pas l'image, mais elle s'affichera quand même via le cache (304).

        die();
    } else { //Jamais vue ou plus de 20 minutes
        if (!isset($_SESSION["l"]))
            $_SESSION["l"] = 0;
        $_SESSION["l"]++;

        //Jamais vue et on affiche l'image.
        die(die(base64_decode("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC40EoIC8wAAAAxJREFUGFdj+M/DAAADGQEMSU/xrQAAAABJRU5ErkJggg=="));
    }
}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width; initial-scale=1.0;">
    </head>
    <body>
        <img src="lol.php?l=1" alt="img"/>
    </body>
</html>

Sur le lien de viki53, il y a une réponse intéressante :

A few additional findings:

The addition no-cache headers such as those output by php's session_start() appear to prevent this second request.

The addition of a Last-Modified: header with a date at least 10 seconds old will also prevent the second request, provided there are no query-string parameters in the url. If a query string is present it seems to go ahead with the second request regardless of the last-modified header's value.

Keith Maika - Bugzilla

J'espère que ma réponse vas t'aider,

Bonne soirée. ;)

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte