/inc/bigUpload.php

https://github.com/ajbetteridge/BigUpload · PHP · 220 lines · 117 code · 28 blank · 75 comment · 13 complexity · 45ce777c468348a82f22774e5c82d196 MD5 · raw file

  1. <?php
  2. class BigUpload
  3. {
  4. /**
  5. * Temporary directory for uploading files
  6. */
  7. const TEMP_DIRECTORY = '../files/tmp/';
  8. /**
  9. * Directory files will be moved to after the upload is completed
  10. */
  11. const MAIN_DIRECTORY = '../files/';
  12. /**
  13. * Max allowed filesize. This is for unsupported browsers and
  14. * as an additional security check in case someone bypasses the js filesize check.
  15. *
  16. * This must match the value specified in main.js
  17. */
  18. const MAX_SIZE = 2147483648;
  19. /**
  20. * Temporary directory
  21. * @var string
  22. */
  23. private $tempDirectory;
  24. /**
  25. * Directory for completed uploads
  26. * @var string
  27. */
  28. private $mainDirectory;
  29. /**
  30. * Name of the temporary file. Used as a reference to make sure chunks get written to the right file.
  31. * @var string
  32. */
  33. private $tempName;
  34. /**
  35. * Constructor function, sets the temporary directory and main directory
  36. */
  37. public function __construct() {
  38. $this->setTempDirectory(self::TEMP_DIRECTORY);
  39. $this->setMainDirectory(self::MAIN_DIRECTORY);
  40. }
  41. /**
  42. * Create a random file name for the file to use as it's being uploaded
  43. * @param string $value Temporary filename
  44. */
  45. public function setTempName($value = null) {
  46. if($value) {
  47. $this->tempName = $value;
  48. }
  49. else {
  50. $this->tempName = mt_rand() . '.tmp';
  51. }
  52. }
  53. /**
  54. * Return the name of the temporary file
  55. * @return string Temporary filename
  56. */
  57. public function getTempName() {
  58. return $this->tempName;
  59. }
  60. /**
  61. * Set the name of the temporary directory
  62. * @param string $value Temporary directory
  63. */
  64. public function setTempDirectory($value) {
  65. $this->tempDirectory = $value;
  66. return true;
  67. }
  68. /**
  69. * Return the name of the temporary directory
  70. * @return string Temporary directory
  71. */
  72. public function getTempDirectory() {
  73. return $this->tempDirectory;
  74. }
  75. /**
  76. * Set the name of the main directory
  77. * @param string $value Main directory
  78. */
  79. public function setMainDirectory($value) {
  80. $this->mainDirectory = $value;
  81. }
  82. /**
  83. * Return the name of the main directory
  84. * @return string Main directory
  85. */
  86. public function getMainDirectory() {
  87. return $this->mainDirectory;
  88. }
  89. /**
  90. * Function to upload the individual file chunks
  91. * @return string JSON object with result of upload
  92. */
  93. public function uploadFile() {
  94. //Make sure the total file we're writing to hasn't surpassed the file size limit
  95. if(file_exists($this->getTempDirectory() . $this->getTempName())) {
  96. if(filesize($this->getTempDirectory() . $this->getTempName()) > self::MAX_SIZE) {
  97. $this->abortUpload();
  98. return json_encode(array(
  99. 'errorStatus' => 1,
  100. 'errorText' => 'File is too large.'
  101. ));
  102. }
  103. }
  104. //Open the raw POST data from php://input
  105. $fileData = file_get_contents('php://input');
  106. //Write the actual chunk to the larger file
  107. $handle = fopen($this->getTempDirectory() . $this->getTempName(), 'a');
  108. fwrite($handle, $fileData);
  109. fclose($handle);
  110. return json_encode(array(
  111. 'key' => $this->getTempName(),
  112. 'errorStatus' => 0
  113. ));
  114. }
  115. /**
  116. * Function for cancelling uploads while they're in-progress; deletes the temp file
  117. * @return string JSON object with result of deletion
  118. */
  119. public function abortUpload() {
  120. if(unlink($this->getTempDirectory() . $this->getTempName())) {
  121. return json_encode(array('errorStatus' => 0));
  122. }
  123. else {
  124. return json_encode(array(
  125. 'errorStatus' => 1,
  126. 'errorText' => 'Unable to delete temporary file.'
  127. ));
  128. }
  129. }
  130. /**
  131. * Function to rename and move the finished file
  132. * @param string $final_name Name to rename the finished upload to
  133. * @return string JSON object with result of rename
  134. */
  135. public function finishUpload($finalName) {
  136. if(rename($this->getTempDirectory() . $this->getTempName(), $this->getMainDirectory() . $finalName)) {
  137. return json_encode(array('errorStatus' => 0));
  138. }
  139. else {
  140. return json_encode(array(
  141. 'errorStatus' => 1,
  142. 'errorText' => 'Unable to move file after uploading.'
  143. ));
  144. }
  145. }
  146. /**
  147. * Basic php file upload function, used for unsupported browsers.
  148. * The output on success/failure is very basic, and it would be best to have these errors return the user to index.html
  149. * with the errors printed on the form, but that is beyond the scope of this project as it is very application specific.
  150. * @return string Success or failure of upload
  151. */
  152. public function postUnsupported() {
  153. $name = $_FILES['bigUploadFile']['name'];
  154. $size = $_FILES['bigUploadFile']['size'];
  155. $tempName = $_FILES['bigUploadFile']['tmp_name'];
  156. if(filesize($tempName) > self::MAX_SIZE) {
  157. return 'File is too large.';
  158. }
  159. if(move_uploaded_file($tempName, $this->getMainDirectory() . $name)) {
  160. return 'File uploaded.';
  161. }
  162. else {
  163. return 'There was an error uploading the file';
  164. }
  165. }
  166. }
  167. //Instantiate the class
  168. $bigUpload = new BigUpload;
  169. //Set the temporary filename
  170. $tempName = null;
  171. if(isset($_GET['key'])) {
  172. $tempName = $_GET['key'];
  173. }
  174. if(isset($_POST['key'])) {
  175. $tempName = $_POST['key'];
  176. }
  177. $bigUpload->setTempName($tempName);
  178. switch($_GET['action']) {
  179. case 'upload':
  180. print $bigUpload->uploadFile();
  181. break;
  182. case 'abort':
  183. print $bigUpload->abortUpload();
  184. break;
  185. case 'finish':
  186. print $bigUpload->finishUpload($_POST['name']);
  187. break;
  188. case 'post-unsupported':
  189. print $bigUpload->postUnsupported();
  190. break;
  191. }
  192. ?>