/ch18/PhpSolutions/File/Upload_01.php

https://gitlab.com/orrisb/php-7-solutions · PHP · 157 lines · 139 code · 15 blank · 3 comment · 25 complexity · 775b38af5e28e5cdcf61b19d71400564 MD5 · raw file

  1. <?php
  2. namespace PhpSolutions\File;
  3. class Upload
  4. {
  5. protected $destination;
  6. protected $max = 51200;
  7. protected $messages = [];
  8. protected $permitted = [
  9. 'image/gif',
  10. 'image/jpeg',
  11. 'image/pjpeg',
  12. 'image/png',
  13. 'image/webp'
  14. ];
  15. protected $newName;
  16. protected $filenames = [];
  17. public function __construct($path) {
  18. if (is_dir($path) && is_writable($path)) {
  19. $this->destination = rtrim($path, '/\\') . DIRECTORY_SEPARATOR;
  20. } else {
  21. throw new \Exception("$path must be a valid, writable directory.");
  22. }
  23. }
  24. public function upload($fieldname, $size = null, array $mime = null, $renameDuplicates = true) {
  25. $uploaded = $_FILES[$fieldname];
  26. if (!is_null($size) && $size > 0) {
  27. $this->max = (int)$size;
  28. }
  29. if (!is_null($mime)) {
  30. $this->permitted = array_merge($this->permitted, $mime);
  31. }
  32. if (is_array($uploaded['name'])) {
  33. // deal with multiple uploads
  34. $numFiles = count($uploaded['name']);
  35. $keys = array_keys($uploaded);
  36. for ($i = 0; $i < $numFiles; $i++) {
  37. $values = array_column($uploaded, $i);
  38. $currentfile = array_combine($keys, $values);
  39. $this->processUpload($currentfile, $renameDuplicates);
  40. }
  41. } else {
  42. $this->processUpload($uploaded, $renameDuplicates);
  43. }
  44. }
  45. public function getMessages() {
  46. return $this->messages;
  47. }
  48. public function getMaxSize() {
  49. return number_format($this->max / 1024, 1) . ' KB';
  50. }
  51. public function getFilenames() {
  52. return $this->filenames;
  53. }
  54. protected function checkFile($file) {
  55. $accept = $this->getErrorLevel($file);
  56. $accept = $this->checkSize($file);
  57. if (!empty($file['type'])) {
  58. $accept = $this->checkType($file);
  59. }
  60. return $accept;
  61. }
  62. protected function getErrorLevel($file) {
  63. switch ($file['error']) {
  64. case 0:
  65. return true;
  66. case 1:
  67. case 2:
  68. $this->messages[] = $file['name'] . ' is too big: (max: ' .
  69. $this->getMaxSize() . ').';
  70. break;
  71. case 3:
  72. $this->messages[] = $file['name'] . ' was only partially
  73. uploaded.';
  74. break;
  75. case 4:
  76. $this->messages[] = 'No file submitted.';
  77. break;
  78. default:
  79. $this->messages[] = 'Sorry, there was a problem uploading ' .
  80. $file['name'];
  81. }
  82. return false;
  83. }
  84. protected function checkSize($file) {
  85. if ($file['error'] == 1 || $file['error'] == 2) {
  86. return false;
  87. } elseif ($file['size'] == 0) {
  88. $this->messages[] = $file['name'] . ' is an empty file.';
  89. return false;
  90. } elseif ($file['size'] > $this->max) {
  91. $this->messages[] = $file['name'] . ' exceeds the maximum size
  92. for a file (' . $this->getMaxSize() . ').';
  93. return false;
  94. }
  95. return true;
  96. }
  97. protected function checkType($file) {
  98. if (!in_array($file['type'], $this->permitted)) {
  99. $this->messages[] = $file['name'] . ' is not permitted type of file.';
  100. return false;
  101. }
  102. return true;
  103. }
  104. protected function checkName($file, $renameDuplicates) {
  105. $this->newName = null;
  106. $nospaces = str_replace(' ', '_', $file['name']);
  107. if ($nospaces != $file['name']) {
  108. $this->newName = $nospaces;
  109. }
  110. if ($renameDuplicates) {
  111. $name = $this->newName ?? $file['name'];
  112. if (file_exists($this->destination . $name)) {
  113. // rename file
  114. $basename = pathinfo($name, PATHINFO_FILENAME);
  115. $extension = pathinfo($name, PATHINFO_EXTENSION);
  116. $this->newName = $basename . '_' . time() . ".$extension";
  117. }
  118. }
  119. }
  120. protected function processUpload($uploaded, $renameDuplicates) {
  121. if ($this->checkFile($uploaded)) {
  122. $this->checkName($uploaded, $renameDuplicates);
  123. $this->moveFile($uploaded);
  124. }
  125. }
  126. protected function moveFile($file) {
  127. $filename = $this->newName ?? $file['name'];
  128. $success = move_uploaded_file($file['tmp_name'],
  129. $this->destination . $filename);
  130. if ($success) {
  131. // add the amended filename to the array of uploaded files
  132. $this->filenames[] = $filename;
  133. $result = $file['name'] . ' was uploaded successfully';
  134. if (!is_null($this->newName)) {
  135. $result .= ', and was renamed ' . $this->newName;
  136. }
  137. $this->messages[] = $result;
  138. } else {
  139. $this->messages[] = 'Could not upload ' . $file['name'];
  140. }
  141. }
  142. }