File.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. /**
  3. * File helper class.
  4. *
  5. * @package Kohana
  6. * @category Helpers
  7. * @author Kohana Team
  8. * @copyright (c) Kohana Team
  9. * @license https://koseven.ga/LICENSE.md
  10. */
  11. class Kohana_File {
  12. /**
  13. * Attempt to get the mime type from a file. This method is horribly
  14. * unreliable, due to PHP being horribly unreliable when it comes to
  15. * determining the mime type of a file.
  16. *
  17. * $mime = File::mime($file);
  18. *
  19. * @param string $filename file name or path
  20. * @return string mime type on success
  21. * @return FALSE on failure
  22. */
  23. public static function mime($filename)
  24. {
  25. // Get the complete path to the file
  26. $filename = realpath($filename);
  27. // Get the extension from the filename
  28. $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
  29. if (preg_match('/^(?:jpe?g|png|[gt]if|bmp|swf)$/', $extension))
  30. {
  31. // Use getimagesize() to find the mime type on images
  32. $file = getimagesize($filename);
  33. if (isset($file['mime']))
  34. return $file['mime'];
  35. }
  36. if (class_exists('finfo', FALSE))
  37. {
  38. if ($info = new finfo(defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME))
  39. {
  40. return $info->file($filename);
  41. }
  42. }
  43. if (ini_get('mime_magic.magicfile') AND function_exists('mime_content_type'))
  44. {
  45. // The mime_content_type function is only useful with a magic file
  46. return mime_content_type($filename);
  47. }
  48. if ( ! empty($extension))
  49. {
  50. return File::mime_by_ext($extension);
  51. }
  52. // Unable to find the mime-type
  53. return FALSE;
  54. }
  55. /**
  56. * Return the mime type of an extension.
  57. *
  58. * $mime = File::mime_by_ext('png'); // "image/png"
  59. *
  60. * @param string $extension php, pdf, txt, etc
  61. * @return string mime type on success
  62. * @return FALSE on failure
  63. */
  64. public static function mime_by_ext($extension)
  65. {
  66. // Load all of the mime types
  67. $mimes = Kohana::$config->load('mimes');
  68. return isset($mimes[$extension]) ? $mimes[$extension][0] : FALSE;
  69. }
  70. /**
  71. * Lookup MIME types for a file
  72. *
  73. * @see Kohana_File::mime_by_ext()
  74. * @param string $extension Extension to lookup
  75. * @return array Array of MIMEs associated with the specified extension
  76. */
  77. public static function mimes_by_ext($extension)
  78. {
  79. // Load all of the mime types
  80. $mimes = Kohana::$config->load('mimes');
  81. return isset($mimes[$extension]) ? ( (array) $mimes[$extension]) : [];
  82. }
  83. /**
  84. * Lookup file extensions by MIME type
  85. *
  86. * @param string $type File MIME type
  87. * @return array|false File extensions matching MIME type or false if none
  88. */
  89. public static function exts_by_mime($type)
  90. {
  91. static $types = [];
  92. // Fill the static array
  93. if (empty($types))
  94. {
  95. foreach (Kohana::$config->load('mimes') as $ext => $mimes)
  96. {
  97. foreach ($mimes as $mime)
  98. {
  99. if ($mime == 'application/octet-stream')
  100. {
  101. // octet-stream is a generic binary
  102. continue;
  103. }
  104. if ( ! isset($types[$mime]))
  105. {
  106. $types[$mime] = [ (string) $ext];
  107. }
  108. elseif ( ! in_array($ext, $types[$mime]))
  109. {
  110. $types[$mime][] = (string) $ext;
  111. }
  112. }
  113. }
  114. }
  115. return isset($types[$type]) ? $types[$type] : FALSE;
  116. }
  117. /**
  118. * Lookup a single file extension by MIME type.
  119. *
  120. * @param string $type MIME type to lookup
  121. * @return string|false First file extension matching or false
  122. */
  123. public static function ext_by_mime($type)
  124. {
  125. $exts = File::exts_by_mime($type);
  126. if ($exts === FALSE)
  127. {
  128. return FALSE;
  129. }
  130. return current($exts);
  131. }
  132. /**
  133. * Split a file into pieces matching a specific size. Used when you need to
  134. * split large files into smaller pieces for easy transmission.
  135. *
  136. * $count = File::split($file);
  137. *
  138. * @param string $filename file to be split
  139. * @param integer $piece_size size, in MB, for each piece to be
  140. * @return integer The number of pieces that were created
  141. */
  142. public static function split($filename, $piece_size = 10)
  143. {
  144. // Open the input file
  145. $file = fopen($filename, 'rb');
  146. // Change the piece size to bytes
  147. $piece_size = floor($piece_size * 1024 * 1024);
  148. // Write files in 8k blocks
  149. $block_size = 1024 * 8;
  150. // Total number of pieces
  151. $pieces = 0;
  152. while ( ! feof($file))
  153. {
  154. // Create another piece
  155. $pieces += 1;
  156. // Create a new file piece
  157. $piece = str_pad($pieces, 3, '0', STR_PAD_LEFT);
  158. $piece = fopen($filename.'.'.$piece, 'wb+');
  159. // Number of bytes read
  160. $read = 0;
  161. do
  162. {
  163. // Transfer the data in blocks
  164. fwrite($piece, fread($file, $block_size));
  165. // Another block has been read
  166. $read += $block_size;
  167. }
  168. while ($read < $piece_size);
  169. // Close the piece
  170. fclose($piece);
  171. }
  172. // Close the file
  173. fclose($file);
  174. return $pieces;
  175. }
  176. /**
  177. * Join a split file into a whole file. Does the reverse of [File::split].
  178. *
  179. * $count = File::join($file);
  180. *
  181. * @param string $filename split filename, without .000 extension
  182. * @return integer The number of pieces that were joined.
  183. */
  184. public static function join($filename)
  185. {
  186. // Open the file
  187. $file = fopen($filename, 'wb+');
  188. // Read files in 8k blocks
  189. $block_size = 1024 * 8;
  190. // Total number of pieces
  191. $pieces = 0;
  192. while (is_file($piece = $filename.'.'.str_pad($pieces + 1, 3, '0', STR_PAD_LEFT)))
  193. {
  194. // Read another piece
  195. $pieces += 1;
  196. // Open the piece for reading
  197. $piece = fopen($piece, 'rb');
  198. while ( ! feof($piece))
  199. {
  200. // Transfer the data in blocks
  201. fwrite($file, fread($piece, $block_size));
  202. }
  203. // Close the piece
  204. fclose($piece);
  205. }
  206. return $pieces;
  207. }
  208. }