diff --git a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
index 8dd882de02..c2400fe564 100644
--- a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
+++ b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
@@ -181,7 +181,7 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
       '#default_value' => $settings['max_filesize'],
       '#description' => t('Enter a value like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes) in order to restrict the allowed file size. If left empty the file sizes will be limited only by PHP\'s maximum post and file upload sizes (current limit <strong>%limit</strong>).', ['%limit' => format_size(Environment::getUploadMaxSize())]),
       '#size' => 10,
-      '#element_validate' => [[get_class($this), 'validateMaxFilesize']],
+      '#element_validate' => [[FileItemMaxFileSizeValidator::class, 'validateMaxFilesize']],
       '#weight' => 5,
     ];
 
@@ -197,11 +197,11 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
   }
 
   /**
-   * Form API callback
+   * Form API callback.
    *
    * Removes slashes from the beginning and end of the destination value and
-   * ensures that the file directory path is not included at the beginning of the
-   * value.
+   * ensures that the file directory path is not included at the beginning of
+   * the value.
    *
    * This function is assigned as an #element_validate callback in
    * fieldSettingsForm().
@@ -220,7 +220,8 @@ public static function validateDirectory($element, FormStateInterface $form_stat
    *
    * This doubles as a convenience clean-up function and a validation routine.
    * Commas are allowed by the end-user, but ultimately the value will be stored
-   * as a space-separated list for compatibility with file_validate_extensions().
+   * as a space-separated list for compatibility with
+   * file_validate_extensions().
    */
   public static function validateExtensions($element, FormStateInterface $form_state) {
     if (!empty($element['#value'])) {
@@ -236,21 +237,6 @@ public static function validateExtensions($element, FormStateInterface $form_sta
     }
   }
 
-  /**
-   * Form API callback.
-   *
-   * Ensures that a size has been entered and that it can be parsed by
-   * \Drupal\Component\Utility\Bytes::toInt().
-   *
-   * This function is assigned as an #element_validate callback in
-   * fieldSettingsForm().
-   */
-  public static function validateMaxFilesize($element, FormStateInterface $form_state) {
-    if (!empty($element['#value']) && !is_numeric(Bytes::toInt($element['#value']))) {
-      $form_state->setError($element, t('The "@name" option must contain a valid value. You may either leave the text field empty or enter a string like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes).', ['@name' => $element['title']]));
-    }
-  }
-
   /**
    * Determines the URI for a file field.
    *
@@ -260,10 +246,9 @@ public static function validateMaxFilesize($element, FormStateInterface $form_st
    * @return string
    *   An unsanitized file directory URI with tokens replaced. The result of
    *   the token replacement is then converted to plain text and returned.
-   *
    * @see \Drupal\Core\Utility\Token::replace()
    */
-  public function getUploadLocation($data = []) {
+  public function getUploadLocation(array $data = []) {
     return static::doGetUploadLocation($this->getSettings(), $data);
   }
 
@@ -281,7 +266,7 @@ public function getUploadLocation($data = []) {
    *
    * @see \Drupal\Core\Utility\Token::replace()
    */
-  protected static function doGetUploadLocation(array $settings, $data = []) {
+  protected static function doGetUploadLocation(array $settings, array $data = []) {
     $destination = trim($settings['file_directory'], '/');
 
     // Replace tokens. As the tokens might contain HTML we convert it to plain
diff --git a/core/modules/file/src/Plugin/Field/FieldType/FileItemMaxFileSizeValidator.php b/core/modules/file/src/Plugin/Field/FieldType/FileItemMaxFileSizeValidator.php
new file mode 100644
index 0000000000..1d1ef40a2e
--- /dev/null
+++ b/core/modules/file/src/Plugin/Field/FieldType/FileItemMaxFileSizeValidator.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace Drupal\file\Plugin\Field\FieldType;
+
+use Drupal\Component\Utility\Bytes;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
+/**
+ * Provides helper methods for max file size value validation.
+ */
+class FileItemMaxFileSizeValidator {
+
+  /**
+   * Holds a string representing a byte size to be validated.
+   *
+   * @var string
+   *   A string size expressed as a number of bytes with optional SI
+   *   or IEC binary unit prefix (e.g. 2, 3K, 5MB, 10G, 6GiB, 8 bytes, 9mbytes).
+   */
+  private static $size;
+
+  /**
+   * Form API callback.
+   *
+   * Ensures that a size has been entered and that it can be parsed by
+   * \Drupal\Component\Utility\Bytes::toInt().
+   *
+   * This function is assigned as an #element_validate callback in
+   * fieldSettingsForm().
+   * @param array $element
+   *   A field element array.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current state of the form.
+   */
+  public static function validateMaxFilesize(array $element, FormStateInterface $form_state) {
+
+    // Spaces are irrelevant to us. Bytes::toInt will process with or without
+    // them. Make our lives easier by just doing away with them.
+    self::$size = self::stripSpacesFromString($element['#value']);
+
+    // Having removed whitespace, if our string is now empty then the user
+    // either entered nothing or a string of whitespace. Accept both cases as
+    // valid.
+    if (empty(self::$size)) {
+      return;
+    }
+
+    // Theoretically self::stringIsValidByteString() should perform strict
+    // enough validation. Passing the string to Bytes::toInt() for added
+    // precaution.
+    if (self::sizeIsValidByteString() || !self::toIntCanParseString()) {
+      $translatable_markup = new TranslatableMarkup('The "@name" option must contain a valid value. You may either leave the text field empty or enter a string like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes).', ['@name' => $element['#title']]);
+      $form_state->setError($element, $translatable_markup);
+    }
+  }
+
+  /**
+   * Validate the given string looks like a byte size string.
+   *
+   * @return bool
+   */
+  private static function sizeIsValidByteString() {
+    return (
+      self::sizeIsNotAlphaNumeric() ||
+      self::sizeNotStartWithNumber() ||
+      self::sizeHasNumbersFollowingAlphaChar()
+    );
+  }
+
+  /**
+   * Strips spaces from a string of text.
+   *
+   * @param string $string
+   *   A string representing a size (5mb, 500GB etc)
+   *
+   * @return string
+   *   Returns the inputted string with spaces removed.
+   */
+  private static function stripSpacesFromString($string) {
+    return trim(preg_replace('/\s+/', '', $string));
+  }
+
+  /**
+   * Determines that a string does not start with a number.
+   *
+   * @return bool
+   *   TRUE if the string does not start with a numeric char, FALSE otherwise.
+   */
+  private static function sizeNotStartWithNumber() {
+    return !preg_match('/^\d/', self::$size);
+  }
+
+  /**
+   * Determines if a string has numberic chars following after alpha chars.
+   *
+   * @return bool
+   *   TRUE if the string has numeric values following after alpha chars.
+   */
+  private static function sizeHasNumbersFollowingAlphaChar() {
+    return (bool) preg_match('/[a-zA-Z]+(\d+)/', self::$size);
+  }
+
+  /**
+   * Determines if a string contains non alphanumeric characters.
+   *
+   * @return bool
+   *   Returns TRUE if non alphanumeric characters are found.
+   */
+  private static function sizeIsNotAlphaNumeric() {
+    return (bool) !preg_match('/^[a-zA-Z0-9]+$/', self::$size);
+  }
+
+  /**
+   * Determines if Bytes:toInt() is able to parse the given string.
+   *
+   * @return bool
+   *   TRUE if string can be parsed by Bytes::toInt(), FALSE otherwise.
+   */
+  private static function toIntCanParseString() {
+    $valid = TRUE;
+    try {
+      Bytes::toInt(self::$size);
+    }
+    catch (\Exception $e) {
+      $valid = FALSE;
+    }
+    return $valid;
+  }
+
+}
diff --git a/core/modules/file/tests/src/Unit/FileItemFieldSettingsFormTest.php b/core/modules/file/tests/src/Unit/FileItemFieldSettingsFormTest.php
new file mode 100644
index 0000000000..d8f7696a2a
--- /dev/null
+++ b/core/modules/file/tests/src/Unit/FileItemFieldSettingsFormTest.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace Drupal\Tests\file\Unit;
+
+use Drupal\Core\Form\FormState;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\file\Plugin\Field\FieldType\FileItemMaxFileSizeValidator;
+use Drupal\Tests\UnitTestCase;
+use Prophecy\Argument;
+
+/**
+ * Tests FileItem's settings form's validation.
+ *
+ * @group file
+ */
+class FileItemFieldSettingsFormTest extends UnitTestCase {
+
+  /**
+   * Tests that a sane Max file size is entered.
+   *
+   * @dataProvider maxFileSizeInputsProvider
+   */
+  public function testValidateMaxfilesize($input, $should_error) {
+
+    $element = [
+      '#title' => 'Maximum upload size',
+      '#value' => $input,
+    ];
+
+    $form_state = $this->prophesize(FormState::class);
+    if ($should_error) {
+      $form_state->setError($element, Argument::type(TranslatableMarkup::class))
+        ->shouldBeCalled();
+    }
+    else {
+      $form_state->setError($element, Argument::type(TranslatableMarkup::class))
+        ->shouldNotBeCalled();
+    }
+    FileItemMaxFileSizeValidator::validateMaxFilesize($element, $form_state->reveal());
+
+  }
+
+  /**
+   * Data provider for testValidateMaxfilesize().
+   *
+   * @return array[]
+   *   Array of inputs and error expectations.
+   */
+  public function maxFileSizeInputsProvider() {
+    return [
+      ['0 bytes', FALSE],
+      ['123456.03 ', TRUE],
+      ['   ', FALSE],
+      ['', FALSE],
+      ['0 K', FALSE],
+      ['100bytes', FALSE],
+      ['10000', FALSE],
+      ['100bytes', FALSE],
+      ['100 bytes', FALSE],
+      ['999989 bytes', FALSE],
+      ['999989bytes', FALSE],
+      ['2', FALSE],
+      ['3K', FALSE],
+      ['5MB', FALSE],
+      ['10G', FALSE],
+      ['6GiB', FALSE],
+      ['8bytes', FALSE],
+      ['9mbytes', FALSE],
+      // Should we allow these spaces?
+      ['1 0 0 0 0 m b y tes', FALSE],
+      ['nonumbers', TRUE],
+      ['bread', TRUE],
+      ['bananas', TRUE],
+      ['1234b1', TRUE],
+      ['543xd1', TRUE],
+      ['-1', TRUE],
+      ['-975', TRUE],
+      [' word ', TRUE],
+      [' word', TRUE],
+      ['word ', TRUE],
+      [' words with spaces ', TRUE],
+      ['words with spaces ', TRUE],
+      [' words with spaces', TRUE],
+      [' 123456 ', FALSE],
+      [' 123456.03 ', TRUE],
+      ['123456.03 ', TRUE],
+      [' 123456.03', TRUE],
+      [' some words & stuff', TRUE],
+    ];
+  }
+
+}
