Hoi,
Prenons l'exemple bien connu de création de vignettes par php. Le problème de ce genre de chose est que si il y a beaucoup de photos à traiter, nous allons dépasser les 30 secondes fatidiques d'exécution.
Pour améliorer les choses, on peut passer par l'ajax pour exécuter cette fonction.Le message d'erreur apparaîtra dans un div de la page principale. C'est un peu mieux pour l'utilisateur qu'une page blanche avec le message d'erreur.
Ceci est bien beau mais l'idéal serait de ne pas avoir de message d'erreur du tout.
La solution est de créer une fonction ajax récursive qui va envoyer une requête au script php autant de fois qu'il y a de photos à traiter.
En pratique, comment ça marche ?
Le script php
<?php
// cest deux premières lignes sont extrêmement importantes pour IE, sinon, celui-ci met en cache le résultat précédent !!
// la troisième étant juste la pour éviter un conflit enter l'utf-8 et l'iso.
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header('Content-type: text/html; charset=iso-8859-1');
$dir='./images';
chdir($dir);
$dir=".";
$handle=opendir($dir);
$i=0;
while (false !== ($file = readdir($handle)))
{
if (!(is_dir($file)) AND ($file!="Thumbs.db") AND ($file!="error_log") AND ($file!=".ftpquota") AND (!file_exists($dir.'/small/'.$file)))
{
$fichier = $dir.'/'.$file;
if(!file_exists($_SERVER['DOUMENT_ROOT']."/admin/photos_ftp/images/small/".$file))
{
if ($image = @imagecreatefromjpeg($fichier))
{
$width = imagesx($image) ;
$height = imagesy($image) ;
$new_height = 150;
$new_width = $new_height * $width / $height;
$thumb = imagecreatetruecolor($new_width,$new_height);
imageAntiAlias($thumb,true);
imageCopyResampled($thumb,$image,0,0,0,0,$new_width,$new_height,$width,$height);
ImageJPEG($thumb, $dir.'/small/'.$file);
chmod($dir.'/small/'.$file,0666);
imagedestroy($image);
$i++;
echo '<br />image '.$file.' créée !';
}
else
{echo 'Echec de création de l\'image <strong>'.$file.'</strong><br />Effacez ce fichier du dossier et recommencez';die();}
break;
}
}
}
if ($i == 0)
echo 'Toutes les photos ont été traitées';
?>
C'est assez basique. Il cherche juste une vignette non-crée, il la crée et sort de la boucle.
Le terme "créée" est important, il va être utilisé comme contrôle par le script javascript.
Le code html basique :
<style type="text/css">
#resultat {
border: 1px solid black;
background-color: #CCDDFF;
height: 200px;
overflow: auto;
}
</style>";
ici l'important est le overflow : auto; pour suivre l'évolution du script
<span onclick=\"makeRequest('small.php')\">Faire les vignettes</span>";
<div id='resultat'></div>
Rien de bien compliqué ici, on peut aussi appliquer un style genre
cursor: pointer;
text-decoration: underline;
dans notre css.
Bon maintenant, les choses sérieuses :
<script type="text/javascript" language="javascript">
function makeRequest(url)
{
http_request = false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
http_request.onreadystatechange = function() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
document.getElementById('resultat').innerHTML += http_request.responseText+'<br />'; // on écrit le résultat dans le div
document.getElementById('resultat').scrollTop = document.getElementById('resultat').scrollHeight; //juste pour se retrouver en bas
if (http_request.responseText.indexOf('créée') != -1) // Si le terme 'créée' est renvoyé par php
{
makeRequest(url) // Récursivité : On repart dans la fonction
}
} else {
alert('There was a problem with the request.');
}
}
}
http_request.open('/GET', url, true);
http_request.send(null);
}
</script>
La syntaxe "http_request.onreadystatechange = function() {" est très importante.
Ca marche comme ça et pas autrement.
ou alors http_request.onreadystatechange = MaFunction;
mais alors, pas d'argument autorisé.
Donc globalement, que fait donc tout ça ?
Au clic sur 'Faire les vignettes' javascript va envoyer une requête asynchrone au script small.php
celui-ci va générer une et une seule vignette si possible.
Si le résultat est ok -> il envois, par un echo "xxxx créée"
Par ce mot clé, javascript envoit une nouvelle requête à small.php
Et ceci, jusqu'à temps que small.php envois autre chose, comme "Echec de création de l'image..." ou "Toutes les photos ont été traitées"
A ce moment, javascript stoppe sa récursivité.
Résultat : toutes les vignettes ont été crées, parfois en plus d'une minute sans timeout et l'utilisateur peut voir le résultat de sa requête dans le div.