* @author Jean-Pascal MILCENT * @author Aurelien PERONNET * @license GPL v3 * @license CECILL v2 * @copyright 1999-2014 Tela Botanica */ class CelImageFormatO { private $config; // @TODO tirer ça de la config private $formats = array('O'); const METHODE_TELECHARGEMENT = 'telecharger'; const METHODE_AFFICHAGE = 'afficher'; // Pas besoin d'étendre Cel ici, surtout que le constructeur // de la classe Cel instancie toujours une connexion à la bdd // dont on a pas besoin ici. Ceci évite de planter le service // quand la bdd est surchargée. public function __construct($config) { $this->config = $config; } public function getRessource() { header('Content-Type: application/json'); echo json_encode($this->obtenirDescriptionService()); } /** * Méthode appelée avec une requête de type GET. */ public function getElement($params) { // suppression des 0 non significatifs à gauche $id = ltrim($params[0], '0'); $format = isset($_GET['format']) ? $_GET['format'] : 'M'; $methode_livraison = isset($_GET['methode']) ? $_GET['methode'] : self::METHODE_AFFICHAGE; if($this->verifierParametres($id, $format, $methode_livraison)) { $gestion_formats_images = new ImageRecreation($this->config); $image_binaire = $gestion_formats_images->creerOuRenvoyerImage($params[0], $format); if($image_binaire) { $this->envoyerImage($id, $image_binaire, $format, $methode_livraison); } else { header("HTTP/1.0 404 Not Found"); echo 'Aucune image ne correspond à cet identifiant'; } } } private function verifierParametres($id, $format, $methode_livraison) { $ok = true; $message = ''; if(!is_numeric($id)) { $message .= "L'identifiant de format doit être un entier. "; $ok = false; } if(!in_array($format, $this->formats)) { $message .= "Le format d'image est inconnu, les formats acceptés sont ".implode(',', $this->formats).". "; $ok = false; } $types_methode_livraison = array(self::METHODE_AFFICHAGE, self::METHODE_TELECHARGEMENT); if (!in_array($methode_livraison, $types_methode_livraison)) { $message .= "Le format de methode de livraison ".$methode_livraison." n'est pas acceptée par le service. ". " Seuls les methodes suivantes sont gérés : ".implode(',', $types_methode_livraison); $ok = false; } if(!empty($message)) { header("HTTP/1.0 400 Bad Request"); echo $message; } return $ok; } private function envoyerImage($id, $image_binaire, $format, $methode) { $gestion_formats_images = new ImageRecreation($this->config); $dossier = $gestion_formats_images->obtenirDossierPourFormat($id, $format); $nom_fichier = $gestion_formats_images->convertirIdBddVersNomFichier($id, $format); $last_modified_time = filemtime($dossier.'/'.$nom_fichier); // On génère l'ETAG faible $etag = 'W/"' . md5($last_modified_time) . '"'; // On définit les bons headers header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $last_modified_time) . " GMT"); header('Cache-Control: public, max-age=604800'); // On peut ici changer la durée de validité du cache header("Etag: $etag"); // On vérifie les headers envoyés dans la requête if ( (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $last_modified_time) || (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $etag === trim($_SERVER['HTTP_IF_NONE_MATCH'])) ) { // On renvoit une 304 si on n'a rien modifié depuis header('HTTP/1.1 304 Not Modified'); exit(); } if ($methode == self::METHODE_AFFICHAGE) { header('Content-Type: image/jpeg'); } else { $this->envoyerHeadersTelechargement($id, $image_binaire, $format); } echo $image_binaire; exit(); } private function envoyerHeadersTelechargement($id, $image_binaire, $format) { if (function_exists('mb_strlen')) { $taille = mb_strlen($image_binaire, '8bit'); } else { $taille = strlen($image_binaire); } // creation du format original $id_avec_zeros = sprintf('%09s', $id) ; $id_avec_zeros_underscores = wordwrap($id_avec_zeros, 3 , '_', true) ; $nom_fichier = $id_avec_zeros_underscores.'_'.$format.'.jpg'; header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.$nom_fichier.'"'); header('Content-Transfer-Encoding: binary'); header('Connection: Keep-Alive'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: '.$taille); } private function obtenirDescriptionService() { $retour = array('description' => 'Ce service peut être appelé afin de visualiser ou bien télécharger les images du cel', 'formats' => $this->formats, 'utilisation' => 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']."/{id} où {id} est l'identifiant numérique de l'image désirée", 'parametres' => array( 'methode' => "Valeurs : afficher, telecharger. Permet de préciser si l'image doit être affichée ou téléchargée", 'format' => "Valeurs : voir la liste ci dessous. Permet de demander un format précis de l'image parmi ceux disponibles ") ); // ^^ c'est marrant non ? $format_formates = array(); foreach ($this->formats as $format) { if ($format == "O") { $format_formates["O"] = array("hauteur" => "dépend de l'image originale", "largeur" => "dépend de l'image originale", "notes" => "Image dans son ratio et sa résolution originale (elle peut éventuellement avoir été compressée en qualité)" ); } else { $description = array(); if (strpos($format, 'R') !== false) { $description[] = "Format carré, rogné pour ne garder que le centre de l'image."; } if (strpos($format, 'C') !== false) { $description[] = "Format carré, si le format contient R, il est rogné, sinon des bandes blanches sont ajoutées pour conserver le ratio."; } if (empty($description)) { $description[] = "Format standard, le ratio original de l'image est conservé"; } $resolution = $this->config['cel']['format_'.$format]; $resolution = explode("_", $resolution); $format_formates[$format] = array("hauteur" => $resolution[0], "largeur" => $resolution[1], "notes" => implode(' ', $description) ); } } $retour['resolutions'] = $format_formates; return $retour; } }