summaryrefslogtreecommitdiff
path: root/src/controller/ImageUploadController.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/controller/ImageUploadController.php')
-rw-r--r--src/controller/ImageUploadController.php184
1 files changed, 184 insertions, 0 deletions
diff --git a/src/controller/ImageUploadController.php b/src/controller/ImageUploadController.php
new file mode 100644
index 0000000..29b8059
--- /dev/null
+++ b/src/controller/ImageUploadController.php
@@ -0,0 +1,184 @@
1<?php
2// src/controller/ImageUploadController.php
3
4declare(strict_types=1);
5
6class ImageUploadController
7{
8 static public function imagickCleanImage(string $image_data, string $local_path, string $format = 'jpeg'): bool // "string" parce que file_get_contents...
9 {
10 try{
11 $imagick = new Imagick();
12 $imagick->readImageBlob($image_data);
13 $imagick->stripImage(); // nettoyage métadonnées
14 $imagick->setImageFormat($format);
15 if($format === 'jpeg'){
16 $imagick->setImageCompression(Imagick::COMPRESSION_JPEG);
17 $imagick->setImageCompressionQuality(85); // optionnel
18 }
19 $imagick->writeImage($local_path); // enregistrement
20 $imagick->clear();
21 $imagick->destroy();
22 return true;
23 }
24 catch(Exception $e){
25 return false;
26 }
27 }
28 static public function curlDownloadImage(string $url, $maxRetries = 3, $timeout = 10): string|false
29 {
30 $attempt = 0;
31 $imageData = false;
32
33 while($attempt < $maxRetries){
34 $ch = curl_init($url); // instance de CurlHandle
35 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
36 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
37 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
38 curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
39 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
40 curl_setopt($ch, CURLOPT_USERAGENT, 'TinyMCE-Image-Downloader');
41
42 $imageData = curl_exec($ch);
43 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
44 //$curlError = curl_error($ch);
45
46 curl_close($ch);
47
48 if($imageData !== false && $httpCode >= 200 && $httpCode < 300){
49 return $imageData;
50 }
51
52 $attempt++;
53 sleep(1);
54 }
55
56 return false; // échec après trois tentatives
57 }
58
59 // téléchargement par le plugin (bouton "insérer une image")
60 static public function imageUploadTinyMce(): void
61 {
62 if(isset($_FILES['file'])){
63 $file = $_FILES['file'];
64 $dest = 'images/';
65 $dest_mini = 'images-mini/';
66
67 // Vérifier si les répertoires existent, sinon les créer
68 if(!is_dir($dest)) {
69 mkdir($dest, 0700, true);
70 }
71 if(!is_dir($dest_mini)) {
72 mkdir($dest_mini, 0700, true);
73 }
74
75 $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif'];
76 $name = Security::secureFileName(pathinfo($file['name'], PATHINFO_FILENAME));
77 $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
78 if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){
79 $extension = 'jpeg';
80 }
81 $file_path = $dest . $name . '_' . uniqid() . '.' . $extension;
82
83 // créer une miniature de l'image
84 //
85
86 if(self::imagickCleanImage(file_get_contents($file['tmp_name']), $file_path, $extension)){ // recréer l’image pour la nettoyer
87 echo json_encode(['location' => $file_path]); // renvoyer l'URL de l'image téléchargée
88 }
89 else{
90 http_response_code(500);
91 echo json_encode(['message' => 'Erreur image non valide']);
92 }
93 }
94 else{
95 http_response_code(400);
96 echo json_encode(['message' => 'Erreur 400: Bad Request']);
97 }
98 die;
99 }
100
101 // collage de HTML => recherche de balises <img>, téléchargement côté serveur et renvoi de l'adresse sur le serveur
102 static public function uploadImageHtml(): void
103 {
104 $json = json_decode(file_get_contents('php://input'), true);
105
106 if(isset($json['image_url'])){
107 $image_data = self::curlDownloadImage($json['image_url']); // téléchargement de l’image par le serveur avec cURL au lieu de file_get_contents
108 $dest = 'images/';
109
110 if(!is_dir($dest)) { // Vérifier si le répertoire existe, sinon le créer
111 mkdir($dest, 0777, true);
112 }
113
114 if($image_data === false){
115 http_response_code(400);
116 echo json_encode(['message' => "Erreur, le serveur n'a pas réussi à télécharger l'image."]);
117 die;
118 }
119
120 $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif'];
121 $url_path = parse_url($json['image_url'], PHP_URL_PATH);
122 $name = Security::secureFileName(pathinfo($url_path, PATHINFO_FILENAME));
123 $extension = strtolower(pathinfo($url_path, PATHINFO_EXTENSION));
124 if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){
125 $extension = 'jpeg';
126 }
127 $local_path = $dest . $name . '_' . uniqid() . '.' . $extension;
128
129 if(self::imagickCleanImage($image_data, $local_path, $extension)){ // recréer l’image pour la nettoyer
130 echo json_encode(['location' => $local_path]); // nouvelle adresse
131 }
132 else{
133 http_response_code(500);
134 echo json_encode(['message' => 'Erreur image non valide']);
135 }
136 }
137 else{
138 echo json_encode(['message' => 'Erreur 400: Bad Request']);
139 }
140 die;
141 }
142
143 // collage simple d'une image (base64 dans le presse-papier) non encapsulée dans du HTML
144 static public function uploadImageBase64(): void
145 {
146 $json = json_decode(file_get_contents('php://input'), true);
147 $dest = 'images/';
148
149 if(!is_dir('images')){
150 mkdir('images', 0777, true);
151 }
152
153 // détection de data:image/ et de ;base64, et capture du format dans $type
154 if(!isset($json['image_base64']) || !preg_match('/^data:image\/(\w+);base64,/', $json['image_base64'], $type)){
155 http_response_code(400);
156 echo json_encode(['message' => 'Données image base64 manquantes ou invalides']);
157 die;
158 }
159
160 $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif'];
161 $extension = strtolower($type[1]);
162 if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){
163 $extension = 'jpeg';
164 }
165
166 $image_data = base64_decode(substr($json['image_base64'], strpos($json['image_base64'], ',') + 1)); // découpe la chaine à la virgule puis convertit en binaire
167 if($image_data === false){
168 http_response_code(400);
169 echo json_encode(['message' => 'Décodage base64 invalide']);
170 die;
171 }
172
173 $local_path = $dest . 'pasted_image_' . uniqid() . '.' . $extension;
174
175 if(self::imagickCleanImage($image_data, $local_path)){
176 echo json_encode(['location' => $local_path]);
177 }
178 else{
179 http_response_code(500);
180 echo json_encode(['message' => 'Erreur image non valide']);
181 }
182 die;
183 }
184} \ No newline at end of file