file.class.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. <?php
  2. /**
  3. * Classe file
  4. *
  5. * Cette classe gère les opérations liées aux fichiers, y compris l'enregistrement,
  6. * la suppression, le téléchargement, et la gestion des répertoires.
  7. */
  8. class file
  9. {
  10. /**
  11. * Enregistre un fichier temporaire dans un répertoire spécifié.
  12. *
  13. * @param array $_temp Tableau contenant les informations du fichier temporaire.
  14. * @param string $_folderFiles Chemin du répertoire où enregistrer le fichier (par défaut DIR_DATAS_FILES).
  15. * @return string|false Retourne le hash MD5 du fichier enregistré ou FALSE en cas d'échec.
  16. */
  17. public static function record(array $_temp, string $_folderFiles = DIR_DATAS_FILES)
  18. {
  19. $md5 = md5_file($_temp["tmp_name"]);
  20. if(self::findM5($md5) == FALSE){
  21. if (copy($_temp["tmp_name"], $_folderFiles . $md5)) {
  22. db::query("INSERT INTO " . DB_T_FILES . " (id, name, size, id_user) VALUES (:id, :name, :size, :id_user)");
  23. db::bind(':id', $md5);
  24. db::bind(':name', $_temp['name']);
  25. db::bind(':size', $_temp['size']);
  26. db::bind(':id_user', session::getId());
  27. try {
  28. db::execute();
  29. return $md5;
  30. } catch (Exception $ex) {
  31. unlink($_folderFiles . $md5);
  32. alert::recError("Erreur #record sur l'import du fichier " . $_temp['name']);
  33. return FALSE;
  34. }
  35. }
  36. } else {
  37. alert::recError("Erreur #record ce fichier a déjà été importé : " . $_temp['name']);
  38. return FALSE;
  39. }
  40. }
  41. /**
  42. * Vérifie les erreurs lors du téléchargement d'un fichier.
  43. *
  44. * @param array $_file Tableau contenant les informations du fichier téléchargé.
  45. * @return array Retourne un tableau avec le statut et la description de l'erreur (le cas échéant).
  46. */
  47. public static function getErrorUpload(array $_file){
  48. $return = [];
  49. if ($_file['error'] === UPLOAD_ERR_INI_SIZE) {
  50. $return = [
  51. "status" => "error",
  52. "description" => "Le fichier téléchargé dépasse la taille maximale autorisée fixé à " . ini_get('upload_max_filesize')
  53. ];
  54. } elseif ($_file['error'] !== UPLOAD_ERR_OK) {
  55. $phpFileUploadErrors = array(
  56. 1 => 'Le fichier téléchargé dépasse la directive upload_max_filesize dans php.ini',
  57. 2 => 'Le fichier téléchargé dépasse la directive MAX_FILE_SIZE spécifiée dans le formulaire HTML',
  58. 3 => 'Le fichier n\'a été que partiellement téléchargé',
  59. 4 => 'Aucun fichier n\'a été téléchargé',
  60. 6 => 'Il manque un dossier temporaire',
  61. 7 => 'Échec de l\'écriture du fichier sur le disque',
  62. 8 => 'Une extension PHP a arrêté le téléchargement du fichier',
  63. );
  64. $return = [
  65. "status" => "error",
  66. "description" => $phpFileUploadErrors[$_file['error']]
  67. ];
  68. } else {
  69. $return = [
  70. "status" => "success"
  71. ];
  72. }
  73. return $return;
  74. }
  75. /**
  76. * Vérifie si un fichier existe dans la base de données à partir de son hash MD5.
  77. *
  78. * @param string $_md5 Hash MD5 du fichier.
  79. * @return bool Retourne TRUE si le fichier existe, FALSE sinon.
  80. */
  81. public static function findM5(string $_md5){
  82. db::query("SELECT "
  83. . "IF(" . DB_T_FILES . ".name IS NOT NULL, TRUE, FALSE) AS exist "
  84. . "FROM " . DB_T_FILES . " "
  85. . "WHERE " . DB_T_FILES . ".id = :md5");
  86. db::bind(':md5', $_md5);
  87. $return = db::single();
  88. return ($return == TRUE) ? TRUE : FALSE;
  89. }
  90. /**
  91. * Supprime un fichier du système de fichiers et de la base de données.
  92. *
  93. * @param string|null $_id Identifiant du fichier à supprimer.
  94. * @param string $_folderFiles Chemin du répertoire contenant le fichier (par défaut DIR_DATAS_FILES).
  95. * @return bool Retourne TRUE en cas de succès, FALSE en cas d'échec.
  96. */
  97. public static function delete(string $_id = NULL, string $_folderFiles = DIR_DATAS_FILES){
  98. if (isset($_id) and $_id != NULL and file_exists($_folderFiles . $_id)) {
  99. if (unlink($_folderFiles . $_id)) {
  100. db::query("DELETE FROM " . DB_T_FILES . " WHERE id = :id");
  101. db::bind(':id', $_id);
  102. try {
  103. db::execute();
  104. return TRUE;
  105. } catch (Exception $ex) {
  106. alert::recError("Erreur lors de la désindexation du fichier");
  107. return FALSE;
  108. }
  109. } else {
  110. alert::recError("Erreur sur la suppression du fichier");
  111. return FALSE;
  112. }
  113. } else {
  114. return FALSE;
  115. }
  116. }
  117. /**
  118. * Télécharge un fichier à partir de son identifiant.
  119. *
  120. * @param string $_id Identifiant du fichier à télécharger.
  121. * @param string $_folderFiles Chemin du répertoire contenant le fichier (par défaut DIR_DATAS_FILES).
  122. * @return string|false Retourne le chemin du fichier ou FALSE si le fichier n'existe pas.
  123. */
  124. public static function download(string $_id, string $_folderFiles = DIR_DATAS_FILES){
  125. if (file_exists($_folderFiles . $_id)) {
  126. return $_folderFiles . $_id;
  127. } else {
  128. return FALSE;
  129. }
  130. }
  131. /**
  132. * Nettoie un répertoire en supprimant les fichiers au-delà d'un certain nombre.
  133. *
  134. * @param string $_path Chemin du répertoire à nettoyer.
  135. * @param int $_nbFiles Nombre maximum de fichiers à conserver (par défaut 5).
  136. * @return bool Retourne TRUE en cas de succès, FALSE en cas d'échec.
  137. */
  138. public static function cleanFilesByOrder(string $_path, int $_nbFiles = 5){
  139. $return = TRUE;
  140. $cpt = 0;
  141. $files = array();
  142. $dir = new DirectoryIterator($_path);
  143. $blackList = array(
  144. ".",
  145. "..",
  146. "index.html",
  147. "index.php"
  148. );
  149. foreach ($dir as $fileinfo) {
  150. $files[$fileinfo->getMTime()] = $fileinfo->getFilename();
  151. }
  152. krsort($files);
  153. foreach ($files as $file) {
  154. if (!in_array($file, $blackList)) {
  155. if ($cpt++ >= $_nbFiles) {
  156. $return = (unlink($_path . $file)) ? TRUE : FALSE;
  157. }
  158. }
  159. }
  160. return $return;
  161. }
  162. /**
  163. * Supprime tous les fichiers d'un répertoire.
  164. *
  165. * @param string $_path Chemin du répertoire à nettoyer.
  166. * @return bool Retourne TRUE en cas de succès, FALSE en cas d'échec.
  167. */
  168. public static function cleanAllFiles(string $_path){
  169. $return = TRUE;
  170. $dir = new DirectoryIterator($_path);
  171. $blackList = array(
  172. ".",
  173. "..",
  174. "index.html",
  175. "index.php"
  176. );
  177. foreach ($dir as $fileinfo) {
  178. if (!in_array($fileinfo->getFilename(), $blackList)) {
  179. $return = (unlink($_path . $fileinfo->getFilename())) ? TRUE : FALSE;
  180. }
  181. }
  182. return $return;
  183. }
  184. /**
  185. * Supprime les fichiers d'un répertoire en fonction de leur ancienneté.
  186. *
  187. * @param string $_path Chemin du répertoire à nettoyer.
  188. * @param int $_limitTime Temps limite en secondes (par défaut 24 heures).
  189. * @return void
  190. */
  191. public static function cleanFilesByTime(string $_path, int $_limitTime = 24 * 3600){
  192. if ($handle = opendir($_path)) {
  193. while (false !== ($file = readdir($handle))) {
  194. $filelastmodified = filemtime($_path . $file);
  195. if ((time() - $filelastmodified) > $_limitTime) {
  196. unlink($_path . $file);
  197. }
  198. }
  199. closedir($handle);
  200. }
  201. }
  202. /**
  203. * Copie un répertoire et son contenu vers un autre emplacement.
  204. *
  205. * @param string $_folder Chemin du répertoire source.
  206. * @param string $_target Chemin du répertoire cible.
  207. * @return void
  208. */
  209. public static function copyFolder(string $_folder, string $_target){
  210. if ($dir = opendir($_folder)) {
  211. mkdir($_target);
  212. while (($file = readdir($dir))) {
  213. if (($file != '.') && ($file != '..')) {
  214. if (is_dir($_folder . '/' . $file)) {
  215. self::copyFolder($_folder . '/' . $file, $_target . '/' . $file);
  216. } else {
  217. copy($_folder . '/' . $file, $_target . '/' . $file);
  218. }
  219. }
  220. }
  221. closedir($dir);
  222. }
  223. }
  224. /**
  225. * Supprime un répertoire et son contenu.
  226. *
  227. * @param string $_dir Chemin du répertoire à supprimer.
  228. * @return bool Retourne TRUE en cas de succès, FALSE en cas d'échec.
  229. */
  230. public static function deleteFolder(string $_dir){
  231. if (is_dir($_dir)) {
  232. $command = "rm -r " . $_dir;
  233. try {
  234. system($command);
  235. return TRUE;
  236. } catch (Exception $ex) {
  237. return FALSE;
  238. }
  239. }
  240. }
  241. /**
  242. * Crée une archive ZIP à partir d'un répertoire.
  243. *
  244. * @param string $_dir Chemin du répertoire à compresser.
  245. * @param string $_name Nom de l'archive ZIP.
  246. * @return string Retourne le nom de l'archive ZIP créée.
  247. */
  248. public static function zip(string $_dir, string $_name){
  249. $zip = new ZipArchive();
  250. $zip_name = $_name . ".zip";
  251. $zip->open($zip_name, ZipArchive::CREATE);
  252. $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($_dir), RecursiveIteratorIterator::LEAVES_ONLY);
  253. foreach ($files as $file) {
  254. if (!$file->isDir()) {
  255. $filePath = $file->getRealPath();
  256. $relativePath = substr($filePath, strlen($_dir));
  257. $zip->addFile($filePath, $relativePath);
  258. }
  259. }
  260. $zip->close();
  261. return $zip_name;
  262. }
  263. /**
  264. * Décompresse une archive ZIP dans un répertoire cible.
  265. *
  266. * @param string $_zip Chemin de l'archive ZIP.
  267. * @param string $_target Chemin du répertoire cible.
  268. * @return string|false Retourne le nom du répertoire décompressé ou FALSE en cas d'échec.
  269. */
  270. public static function unzip(string $_zip, string $_target){
  271. if (is_file($_zip)) {
  272. $zipInfo = pathinfo($_zip);
  273. if ($zipInfo["extension"] == "zip") {
  274. $command = "unzip -q " . $_zip . " -d " . $_target . $zipInfo["filename"];
  275. try {
  276. system($command);
  277. return $zipInfo["filename"];
  278. } catch (Exception $ex) {
  279. return FALSE;
  280. }
  281. }
  282. }
  283. return FALSE;
  284. }
  285. /**
  286. * Calcule la taille totale d'un répertoire.
  287. *
  288. * @param string $_rep Chemin du répertoire.
  289. * @return int Retourne la taille totale du répertoire en octets.
  290. */
  291. public static function sizeFolder(string $_rep){
  292. $Racine = opendir($_rep);
  293. $Taille = 0;
  294. while ($Dossier = readdir($Racine)) {
  295. if ($Dossier != '..' and $Dossier != '.') {
  296. //Ajoute la taille du sous dossier
  297. if (is_dir($_rep . '/' . $Dossier)) $Taille += self::sizeFolder($_rep . '/' .
  298. $Dossier);
  299. //Ajoute la taille du fichier
  300. else $Taille += filesize($_rep . '/' . $Dossier);
  301. }
  302. }
  303. closedir($Racine);
  304. return $Taille;
  305. }
  306. }