diff --git a/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php b/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php
index 15aed5280030271f71ad31b0ae4ccf435dba11bc..7aa90224fc0f935e92b62df2a4d96002658d66a2 100644
--- a/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php
+++ b/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php
@@ -4,21 +4,25 @@
 
 use Drupal\Component\Render\PlainTextOutput;
 use Drupal\Component\Utility\Crypt;
-use Drupal\Core\Config\Config;
+use Drupal\Core\DependencyInjection\DeprecatedServicePropertyTrait;
 use Drupal\Core\Entity\EntityFieldManagerInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\File\Event\FileUploadSanitizeNameEvent;
 use Drupal\Core\File\Exception\FileException;
+use Drupal\Core\File\Exception\FileExistsException;
 use Drupal\Core\File\FileExists;
 use Drupal\Core\File\FileSystemInterface;
-use Drupal\Core\Lock\LockBackendInterface;
+use Drupal\Core\File\MimeType\MimeTypeGuesser;
+use Drupal\Core\Lock\LockAcquiringException;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\Core\Utility\Token;
 use Drupal\file\Entity\File;
 use Drupal\file\Upload\ContentDispositionFilenameParser;
+use Drupal\file\Upload\FileUploadHandler;
 use Drupal\file\Upload\FileUploadLocationTrait;
 use Drupal\file\Upload\InputStreamFileWriterInterface;
+use Drupal\file\Upload\InputStreamUploadedFile;
 use Drupal\file\Validation\FileValidatorInterface;
 use Drupal\file\Validation\FileValidatorSettingsTrait;
 use Drupal\rest\Attribute\RestResource;
@@ -37,7 +41,6 @@
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
 use Symfony\Component\Routing\Route;
-use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
 
 /**
  * File upload resource.
@@ -60,6 +63,7 @@
 )]
 class FileUploadResource extends ResourceBase {
 
+  use DeprecatedServicePropertyTrait;
   use FileValidatorSettingsTrait;
   use EntityResourceValidationTrait {
     validate as resourceValidate;
@@ -95,135 +99,42 @@ class FileUploadResource extends ResourceBase {
   const BYTES_TO_READ = 8192;
 
   /**
-   * The file system service.
-   *
-   * @var \Drupal\Core\File\FileSystemInterface
-   */
-  protected $fileSystem;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The entity field manager.
-   *
-   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
-   */
-  protected $entityFieldManager;
-
-  /**
-   * The currently authenticated user.
-   *
-   * @var \Drupal\Core\Session\AccountInterface
-   */
-  protected $currentUser;
-
-  /**
-   * The MIME type guesser.
-   *
-   * @var \Symfony\Component\Mime\MimeTypeGuesserInterface
-   */
-  protected $mimeTypeGuesser;
-
-  /**
-   * The token replacement instance.
-   *
-   * @var \Drupal\Core\Utility\Token
-   */
-  protected $token;
-
-  /**
-   * The lock service.
-   *
-   * @var \Drupal\Core\Lock\LockBackendInterface
-   */
-  protected $lock;
-
-  /**
-   * @var \Drupal\Core\Config\ImmutableConfig
-   */
-  protected $systemFileConfig;
-
-  /**
-   * The event dispatcher to dispatch the filename sanitize event.
-   *
-   * @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface
-   */
-  protected $eventDispatcher;
-
-  /**
-   * The file validator.
-   *
-   * @var \Drupal\file\Validation\FileValidatorInterface
-   */
-  protected FileValidatorInterface $fileValidator;
-
-  /**
-   * The input stream file writer.
-   */
-  protected InputStreamFileWriterInterface $inputStreamFileWriter;
-
-  /**
-   * Constructs a FileUploadResource instance.
-   *
-   * @param array $configuration
-   *   A configuration array containing information about the plugin instance.
-   * @param string $plugin_id
-   *   The plugin_id for the plugin instance.
-   * @param mixed $plugin_definition
-   *   The plugin implementation definition.
-   * @param array $serializer_formats
-   *   The available serialization formats.
-   * @param \Psr\Log\LoggerInterface $logger
-   *   A logger instance.
-   * @param \Drupal\Core\File\FileSystemInterface $file_system
-   *   The file system service.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
-   *   The entity field manager.
-   * @param \Drupal\Core\Session\AccountInterface $current_user
-   *   The currently authenticated user.
-   * @param \Symfony\Component\Mime\MimeTypeGuesserInterface $mime_type_guesser
-   *   The MIME type guesser.
-   * @param \Drupal\Core\Utility\Token $token
-   *   The token replacement instance.
-   * @param \Drupal\Core\Lock\LockBackendInterface $lock
-   *   The lock service.
-   * @param \Drupal\Core\Config\Config $system_file_config
-   *   The system file configuration.
-   * @param \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $event_dispatcher
-   *   The event dispatcher service.
-   * @param \Drupal\file\Validation\FileValidatorInterface|null $file_validator
-   *   The file validator service.
-   * @param \Drupal\file\Upload\InputStreamFileWriterInterface|null $input_stream_file_writer
-   *   The input stream file writer.
+   * {@inheritdoc}
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, $serializer_formats, LoggerInterface $logger, FileSystemInterface $file_system, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, AccountInterface $current_user, $mime_type_guesser, Token $token, LockBackendInterface $lock, Config $system_file_config, EventDispatcherInterface $event_dispatcher, FileValidatorInterface $file_validator = NULL, InputStreamFileWriterInterface $input_stream_file_writer = NULL) {
+  protected array $deprecatedProperties = [
+    'currentUser' => 'current_user',
+    'mimeTypeGuesser' => 'mime_type.guesser',
+    'token' => 'token',
+    'lock' => 'lock',
+    'eventDispatcher' => 'event_dispatcher',
+  ];
+
+  public function __construct(
+    array $configuration,
+    $plugin_id,
+    $plugin_definition,
+    $serializer_formats,
+    LoggerInterface $logger,
+    protected FileSystemInterface $fileSystem,
+    protected EntityTypeManagerInterface $entityTypeManager,
+    protected EntityFieldManagerInterface $entityFieldManager,
+    protected FileValidatorInterface | AccountInterface $fileValidator,
+    protected InputStreamFileWriterInterface | MimeTypeGuesser $inputStreamFileWriter,
+    protected FileUploadHandler | Token $fileUploadHandler,
+  ) {
     parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
-    $this->fileSystem = $file_system;
-    $this->entityTypeManager = $entity_type_manager;
-    $this->entityFieldManager = $entity_field_manager;
-    $this->currentUser = $current_user;
-    $this->mimeTypeGuesser = $mime_type_guesser;
-    $this->token = $token;
-    $this->lock = $lock;
-    $this->systemFileConfig = $system_file_config;
-    $this->eventDispatcher = $event_dispatcher;
-    if (!$file_validator) {
-      @trigger_error('Calling ' . __METHOD__ . '() without the $file_validator argument is deprecated in drupal:10.2.0 and is required in drupal:11.0.0. See https://www.drupal.org/node/3363700', E_USER_DEPRECATED);
-      $file_validator = \Drupal::service('file.validator');
+    if (!$fileValidator instanceof FileValidatorInterface) {
+      @trigger_error('Passing a \Drupal\Core\Session\AccountInterface to ' . __METHOD__ . '() as argument 9 is deprecated in drupal:10.3.0 and will be removed before drupal:11.0.0. Pass a \Drupal\file\Validation\FileValidatorInterface instead. See https://www.drupal.org/node/3402032', E_USER_DEPRECATED);
+      $this->fileValidator = \Drupal::service('file.validator');
+    }
+    if (!$inputStreamFileWriter instanceof InputStreamFileWriterInterface) {
+      @trigger_error('Passing a \Drupal\Core\File\MimeType\MimeTypeGuesser to ' . __METHOD__ . '() as argument 10 is deprecated in drupal:10.3.0 and will be removed before drupal:11.0.0. Pass an \Drupal\file\Upload\InputStreamFileWriterInterface instead. See https://www.drupal.org/node/3402032', E_USER_DEPRECATED);
+      $this->inputStreamFileWriter = \Drupal::service('file.input_stream_file_writer');
     }
-    $this->fileValidator = $file_validator;
-    if (!$input_stream_file_writer) {
-      @trigger_error('Calling ' . __METHOD__ . '() without the $input_stream_file_writer argument is deprecated in drupal:10.3.0 and is required in drupal:11.0.0. See https://www.drupal.org/node/3380607', E_USER_DEPRECATED);
-      $input_stream_file_writer = \Drupal::service('file.input_stream_file_writer');
+    if (!$fileUploadHandler instanceof FileUploadHandler) {
+      @trigger_error('Passing a \Drupal\Core\Utility\Token to ' . __METHOD__ . '() as argument 11 is deprecated in drupal:10.3.0 and will be removed before drupal:11.0.0. Pass an \Drupal\file\Upload\FileUploadHandler instead. See https://www.drupal.org/node/3402032', E_USER_DEPRECATED);
+      $this->fileUploadHandler = \Drupal::service('file.upload_handler');
     }
-    $this->inputStreamFileWriter = $input_stream_file_writer;
   }
 
   /**
@@ -239,14 +150,9 @@ public static function create(ContainerInterface $container, array $configuratio
       $container->get('file_system'),
       $container->get('entity_type.manager'),
       $container->get('entity_field.manager'),
-      $container->get('current_user'),
-      $container->get('file.mime_type.guesser'),
-      $container->get('token'),
-      $container->get('lock'),
-      $container->get('config.factory')->get('system.file'),
-      $container->get('event_dispatcher'),
       $container->get('file.validator'),
-      $container->get('file.input_stream_file_writer')
+      $container->get('file.input_stream_file_writer'),
+      $container->get('file.upload_handler'),
     );
   }
 
@@ -282,10 +188,7 @@ public function permissions() {
    *   or when temporary files cannot be moved to their new location.
    */
   public function post(Request $request, $entity_type_id, $bundle, $field_name) {
-    $filename = ContentDispositionFilenameParser::parseFilename($request);
-
     $field_definition = $this->validateAndLoadFieldDefinition($entity_type_id, $bundle, $field_name);
-
     $destination = $this->getUploadDestination($field_definition);
 
     // Check the destination file path is writable.
@@ -293,82 +196,59 @@ public function post(Request $request, $entity_type_id, $bundle, $field_name) {
       throw new HttpException(500, 'Destination file path is not writable');
     }
 
-    $validators = $this->getFileUploadValidators($field_definition->getSettings());
-
-    $prepared_filename = $this->prepareFilename($filename, $validators);
-
-    // Create the file.
-    $file_uri = "{$destination}/{$prepared_filename}";
-
-    $temp_file_path = $this->streamUploadData();
-
-    $file_uri = $this->fileSystem->getDestinationFilename($file_uri, FileExists::Rename);
+    $settings = $field_definition->getSettings();
+    $validators = $this->getFileUploadValidators($settings);
+    if (!array_key_exists('FileExtension', $validators) && $settings['file_extensions'] === '') {
+      // An empty string means 'all file extensions' but the FileUploadHandler
+      // needs the FileExtension entry to be present and empty in order for this
+      // to be respected. An empty array means 'all file extensions'.
+      // @see \Drupal\file\Upload\FileUploadHandler::handleExtensionValidation
+      $validators['FileExtension'] = [];
+    }
 
-    // Lock based on the prepared file URI.
-    $lock_id = $this->generateLockIdFromFileUri($file_uri);
+    try {
+      $filename = ContentDispositionFilenameParser::parseFilename($request);
+      $tempPath = $this->inputStreamFileWriter->writeStreamToFile();
+      $uploadedFile = new InputStreamUploadedFile($filename, $filename, $tempPath, @filesize($tempPath));
 
-    if (!$this->lock->acquire($lock_id)) {
-      throw new HttpException(503, sprintf('File "%s" is already locked for writing', $file_uri), NULL, ['Retry-After' => 1]);
+      $result = $this->fileUploadHandler->handleFileUpload($uploadedFile, $validators, $destination, FileExists::Rename, FALSE);
+    }
+    catch (LockAcquiringException $e) {
+      throw new HttpException(503, $e->getMessage(), NULL, ['Retry-After' => 1]);
+    }
+    catch (UploadException $e) {
+      $this->logger->error('Input data could not be read');
+      throw new HttpException(500, 'Input file data could not be read', $e);
+    }
+    catch (CannotWriteFileException $e) {
+      $this->logger->error('Temporary file data for could not be written');
+      throw new HttpException(500, 'Temporary file data could not be written', $e);
+    }
+    catch (NoFileException $e) {
+      $this->logger->error('Temporary file could not be opened for file upload');
+      throw new HttpException(500, 'Temporary file could not be opened', $e);
+    }
+    catch (FileExistsException $e) {
+      throw new HttpException(statusCode: 500, message: $e->getMessage(), previous: $e);
+    }
+    catch (FileException $e) {
+      throw new HttpException(500, 'Temporary file could not be moved to file location');
     }
 
-    // Begin building file entity.
-    $file = File::create([]);
-    $file->setOwnerId($this->currentUser->id());
-    $file->setFilename($prepared_filename);
-    $file->setMimeType($this->mimeTypeGuesser->guessMimeType($prepared_filename));
-    $file->setFileUri($temp_file_path);
-    // Set the size. This is done in File::preSave() but we validate the file
-    // before it is saved.
-    $file->setSize(@filesize($temp_file_path));
-
-    // Validate the file against field-level validators first while the file is
-    // still a temporary file. Validation is split up in 2 steps to be the same
-    // as in \Drupal\file\Upload\FileUploadHandler::handleFileUpload().
-    // For backwards compatibility this part is copied from ::validate() to
-    // leave that method behavior unchanged.
-    // @todo Improve this with a file uploader service in
-    //   https://www.drupal.org/project/drupal/issues/2940383
-    $violations = $this->fileValidator->validate($file, $validators);
-
-    if (count($violations) > 0) {
+    if ($result->hasViolations()) {
       $message = "Unprocessable Entity: file validation failed.\n";
       $errors = [];
-      foreach ($violations as $violation) {
+      foreach ($result->getViolations() as $violation) {
         $errors[] = PlainTextOutput::renderFromHtml($violation->getMessage());
       }
       $message .= implode("\n", $errors);
 
       throw new UnprocessableEntityHttpException($message);
     }
-
-    $file->setFileUri($file_uri);
-    // Update the filename with any changes as a result of security or renaming
-    // due to an existing file.
-    // @todo Remove this duplication by replacing with FileUploadHandler. See
-    // https://www.drupal.org/project/drupal/issues/3401734
-    $file->setFilename($this->fileSystem->basename($file->getFileUri()));
-
-    // Move the file to the correct location after validation. Use
-    // FileExists::Error as the file location has already been
-    // determined above in FileSystem::getDestinationFilename().
-    try {
-      $this->fileSystem->move($temp_file_path, $file_uri, FileExists::Error);
-    }
-    catch (FileException $e) {
-      throw new HttpException(500, 'Temporary file could not be moved to file location');
-    }
-
-    // Second step of the validation on the file object itself now.
-    $this->resourceValidate($file);
-
-    $file->save();
-
-    $this->lock->release($lock_id);
-
     // 201 Created responses return the newly created entity in the response
     // body. These responses are not cacheable, so we add no cacheability
     // metadata here.
-    return new ModifiedResourceResponse($file, 201);
+    return new ModifiedResourceResponse($result->getFile(), 201);
   }
 
   /**
@@ -380,8 +260,14 @@ public function post(Request $request, $entity_type_id, $bundle, $field_name) {
    * @throws \Symfony\Component\HttpKernel\Exception\HttpException
    *   Thrown when input data cannot be read, the temporary file cannot be
    *   opened, or the temporary file cannot be written.
+   *
+   * @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. There is no
+   *   replacement.
+   *
+   * @see https://www.drupal.org/node/3402032
    */
   protected function streamUploadData(): string {
+    @\trigger_error('Calling ' . __METHOD__ . '() is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. There is no replacement. See https://www.drupal.org/node/3402032', E_USER_DEPRECATED);
     // Catch and throw the exceptions that REST expects.
     try {
       $temp_file_path = $this->inputStreamFileWriter->writeStreamToFile();
@@ -476,12 +362,18 @@ protected function validateAndLoadFieldDefinition($entity_type_id, $bundle, $fie
    *
    * @return string
    *   The prepared/munged filename.
+   *
+   * @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. There is no
+   *   replacement.
+   *
+   * @see https://www.drupal.org/node/3402032
+   * @see https://www.drupal.org/node/3402032
    */
   protected function prepareFilename($filename, array &$validators) {
-    // The actual extension validation occurs in
-    // \Drupal\file\Plugin\rest\resource\FileUploadResource::validate().
+    @\trigger_error('Calling ' . __METHOD__ . '() is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. There is no replacement. See https://www.drupal.org/node/3402032', E_USER_DEPRECATED);
     $extensions = $validators['FileExtension']['extensions'] ?? '';
     $event = new FileUploadSanitizeNameEvent($filename, $extensions);
+    // @phpstan-ignore-next-line
     $this->eventDispatcher->dispatch($event);
     return $event->getFilename();
   }
@@ -507,6 +399,7 @@ protected function getUploadLocation(array $settings) {
 
     // Replace tokens. As the tokens might contain HTML we convert it to plain
     // text.
+    // @phpstan-ignore-next-line
     $destination = PlainTextOutput::renderFromHtml($this->token->replace($destination, []));
     return $settings['uri_scheme'] . '://' . $destination;
   }
diff --git a/core/modules/file/src/Upload/FileUploadHandler.php b/core/modules/file/src/Upload/FileUploadHandler.php
index 2512e7ceb14776c4cd1c7092127fa9ea2de53243..1247f59a157386e7fdd5efde2ac05e2ff6998b1e 100644
--- a/core/modules/file/src/Upload/FileUploadHandler.php
+++ b/core/modules/file/src/Upload/FileUploadHandler.php
@@ -376,9 +376,6 @@ public function handleFileUpload(UploadedFileInterface $uploadedFile, array $val
   /**
    * Move the uploaded file from the temporary path to the destination.
    *
-   * @todo Allows a sub-class to override this method in order to handle
-   * raw file uploads in https://www.drupal.org/project/drupal/issues/2940383.
-   *
    * @param \Drupal\file\Upload\UploadedFileInterface $uploadedFile
    *   The uploaded file.
    * @param string $uri
@@ -389,8 +386,13 @@ public function handleFileUpload(UploadedFileInterface $uploadedFile, array $val
    *
    * @see https://www.drupal.org/project/drupal/issues/2940383
    */
-  protected function moveUploadedFile(UploadedFileInterface $uploadedFile, string $uri) {
-    return $this->fileSystem->moveUploadedFile($uploadedFile->getRealPath(), $uri);
+  protected function moveUploadedFile(UploadedFileInterface $uploadedFile, string $uri): bool {
+    if ($uploadedFile instanceof FormUploadedFile) {
+      return $this->fileSystem->moveUploadedFile($uploadedFile->getRealPath(), $uri);
+    }
+    // We use FileExists::Error) as the file location has already
+    // been determined above in FileSystem::getDestinationFilename().
+    return $this->fileSystem->move($uploadedFile->getRealPath(), $uri, FileExists::Error);
   }
 
   /**
diff --git a/core/modules/file/src/Upload/InputStreamUploadedFile.php b/core/modules/file/src/Upload/InputStreamUploadedFile.php
new file mode 100644
index 0000000000000000000000000000000000000000..281eb6ce6d87d19f7b24a30c44b420c9b4197ba2
--- /dev/null
+++ b/core/modules/file/src/Upload/InputStreamUploadedFile.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace Drupal\file\Upload;
+
+use Symfony\Component\Validator\ConstraintViolationList;
+use Symfony\Component\Validator\ConstraintViolationListInterface;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
+
+/**
+ * An uploaded file from an input stream.
+ */
+final class InputStreamUploadedFile implements UploadedFileInterface {
+
+  /**
+   * Creates a new InputStreamUploadedFile.
+   */
+  public function __construct(
+    protected readonly string $clientOriginalName,
+    protected readonly string $filename,
+    protected readonly string $realPath,
+    protected readonly int | false $size,
+  ) {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getClientOriginalName(): string {
+    return $this->clientOriginalName;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSize(): int {
+    return $this->size;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRealPath(): string | false {
+    return $this->realPath;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFilename(): string {
+    return $this->filename;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function supportsMoveUploadedFile(): bool {
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPathname(): string {
+    throw new \BadMethodCallException(__METHOD__ . ' not implemented');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isValid(): bool {
+    throw new \BadMethodCallException(__METHOD__ . ' not implemented');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getErrorMessage(): string {
+    throw new \BadMethodCallException(__METHOD__ . ' not implemented');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getError(): int {
+    throw new \BadMethodCallException(__METHOD__ . ' not implemented');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate(ValidatorInterface $validator, array $options = []): ConstraintViolationListInterface {
+    return new ConstraintViolationList();
+  }
+
+}
diff --git a/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php b/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php
index 36aa1b00b973182c557655ece957dddca7b5d683..965ef778a51d40ad7a7eff1aa7a8ddba90cfcc4c 100644
--- a/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php
@@ -13,6 +13,7 @@
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\file\Entity\File;
+use Drupal\file\FileInterface;
 use Drupal\rest\RestResourceConfigInterface;
 use Drupal\user\Entity\User;
 use GuzzleHttp\RequestOptions;
@@ -28,7 +29,7 @@ abstract class FileUploadResourceTestBase extends ResourceTestBase {
   /**
    * {@inheritdoc}
    */
-  protected static $modules = ['rest_test', 'entity_test', 'file'];
+  protected static $modules = ['rest_test', 'entity_test', 'file', 'user'];
 
   /**
    * {@inheritdoc}
@@ -354,7 +355,7 @@ public function testPostFileUploadDuplicateFileRaceCondition() {
 
     // Make the same request again. The upload should fail validation.
     $response = $this->fileRequest($uri, $this->testFileData);
-    $this->assertResourceErrorResponse(422, PlainTextOutput::renderFromHtml("Unprocessable Entity: validation failed.\nuri: The file public://foobar/example.txt already exists. Enter a unique file URI.\n"), $response);
+    $this->assertResourceErrorResponse(422, PlainTextOutput::renderFromHtml("Unprocessable Entity: file validation failed.\nThe file public://foobar/example.txt already exists. Enter a unique file URI."), $response);
   }
 
   /**
@@ -683,6 +684,7 @@ protected function getExpectedUnauthorizedAccessMessage($method) {
   protected function getExpectedNormalizedEntity($fid = 1, $expected_filename = 'example.txt', $expected_as_filename = FALSE) {
     $author = User::load(static::$auth ? $this->account->id() : 0);
     $file = File::load($fid);
+    $this->assertInstanceOf(FileInterface::class, $file);
 
     $expected_normalization = [
       'fid' => [