1 /* 2 * Hunt - A high-level D Programming Language Web framework that encourages rapid development and clean, pragmatic design. 3 * 4 * Copyright (C) 2015-2019, HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.framework.file.UploadedFile; 13 14 import hunt.framework.file.File; 15 import hunt.framework.Simplify; 16 17 18 class UploadedFile : File 19 { 20 private int _errorCode = 0; 21 private string _errorMessage = "Unknow error."; 22 private string _originalName; 23 private string _mimeType; 24 25 /** 26 * Accepts the information of the uploaded file as provided by the PHP global $_FILES. 27 * 28 * The file object is only created when the uploaded file is valid (i.e. when the 29 * isValid() method returns true). Otherwise the only methods that could be called 30 * on an UploadedFile instance are: 31 * 32 * * getClientOriginalName, 33 * * getClientMimeType, 34 * * isValid, 35 * * getError. 36 * 37 * Calling any other method on an non-valid instance will cause an unpredictable result. 38 * 39 * @param string $path The full temporary path to the file 40 * @param string $originalName The original file name of the uploaded file 41 * @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream 42 * @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK 43 * @param bool $test Whether the test mode is active 44 * Local files are used in test mode hence the code should not enforce HTTP uploads 45 * 46 * @throws FileException If file_uploads is disabled 47 * @throws FileNotFoundException If the file does not exist 48 */ 49 public this(string path, string originalName, string mimeType = null, int errorCode = 0) 50 { 51 this._originalName = this.getName(originalName); 52 this._mimeType = mimeType is null ? "application/octet-stream" : mimeType; 53 this._errorCode = errorCode; 54 55 super(path, false); 56 } 57 58 /** 59 * Returns the original file name. 60 * 61 * It is extracted from the request from which the file has been uploaded. 62 * Then it should not be considered as a safe value. 63 * 64 * @return string|null The original name 65 */ 66 public string originalName() 67 { 68 return this._originalName; 69 } 70 71 /** 72 * Returns the original file extension. 73 * 74 * It is extracted from the original file name that was uploaded. 75 * Then it should not be considered as a safe value. 76 * 77 * @return string The extension 78 */ 79 override public string extension() 80 { 81 import std.string : lastIndexOf, replace; 82 83 string extensionName; 84 85 extensionName = this.path().replace("\\", "/"); 86 extensionName = extensionName[lastIndexOf(extensionName, '/')..$]; 87 88 return extensionName; 89 } 90 91 /** 92 * Returns the file mime type. 93 * 94 * The client mime type is extracted from the request from which the file 95 * was uploaded, so it should not be considered as a safe value. 96 * 97 * For a trusted mime type, use getMimeType() instead (which guesses the mime 98 * type based on the file content). 99 * 100 * @return string|null The mime type 101 * 102 * @see getMimeType() 103 */ 104 override public string mimeType() 105 { 106 return this._mimeType; 107 } 108 109 /** 110 * Returns the upload error. 111 * 112 * If the upload was successful, the constant UPLOAD_ERR_OK is returned. 113 * Otherwise one of the other UPLOAD_ERR_XXX constants is returned. 114 * 115 * @return int The upload error 116 */ 117 public int getErrorCode() 118 { 119 return this._errorCode; 120 } 121 122 /** 123 * Returns whether the file was uploaded successfully. 124 * 125 * @return bool True if the file has been uploaded with HTTP and no error occurred 126 */ 127 public bool isValid() 128 { 129 return !this._errorCode; 130 } 131 132 /** 133 * Returns the maximum size of an uploaded file as configured in php.ini. 134 * 135 * @return int The maximum size of an uploaded file in bytes 136 */ 137 public static long maxSize() 138 { 139 return config().upload.maxSize; 140 } 141 142 /** 143 * Store the uploaded file on a filesystem disk. 144 * 145 * @param string path 146 * @return false 147 */ 148 public bool store(string path) 149 { 150 return this.move(path); 151 } 152 153 /** 154 * Returns an informative upload error message. 155 * 156 * @return string The error message regarding the specified error code 157 */ 158 public string getErrorMessage() 159 { 160 // static $errors = [ 161 // UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).', 162 // UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.', 163 // UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.', 164 // UPLOAD_ERR_NO_FILE => 'No file was uploaded.', 165 // UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.', 166 // UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.', 167 // UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.', 168 // ]; 169 170 // $errorCode = this._errorCode; 171 // $maxFilesize = UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0; 172 // $message = isset($errors[$errorCode]) ? $errors[$errorCode] : 'The file "%s" was not uploaded due to an unknown error.'; 173 // return sprintf($message, this.getClientOriginalName(), $maxFilesize); 174 175 return this._errorMessage; 176 } 177 }