Change record status: 
Project: 
Introduced in branch: 
10.2.x
Introduced in version: 
10.2.0
Description: 

system_retrieve_file() has been deprecated. New code should use one of the Drupal services for file operations.

Calling code should handle exceptions and set flash messages or logging as required.

Before:

<?php
$file = system_retrieve_file($url, $destination, $managed, $replace);
?>

After:

<?php
use Drupal\Core\File\FileExists;
use Drupal\Core\FileTransfer\FileTransferException;
use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\Exception\InvalidStreamWrapperException;

try {
  $data = (string) \Drupal::httpClient()->get($url)->getBody();

  // Use the correct service depending on whether you want a managed file or not.
  // For unmanaged files, use this:
  $file = \Drupal::service('file_system')->saveData($data, $destination, FileExists::Replace);
  // For managed files, use this:
  $file = \Drupal::service('file.repository')->writeData($data, $destination, FileExists::Replace);
}
catch (FileTransferException $e) {
  \Drupal::messenger()->addError(t('Failed to fetch file due to error "%error"', ['%error' => $e->getMessage()]));
}
catch (FileException | InvalidStreamWrapperException $e) {
  \Drupal::messenger()->addError(t('Failed to save file due to error "%error"', ['%error' => $e->getMessage()]));
}
?>
Impacts: 
Module developers

Comments

micahw156’s picture

We could not find \Drupal\file\ManagedFileFetcher or file.fetcher.managed but it appears that the file.repository service will do what we need.

  $data = (string) \Drupal::httpClient()->get($url)->getBody();
  return \Drupal::service('file.repository')->writeData($data, $destination, FileSystemInterface::EXISTS_REPLACE);

Also, could not find TransferException but FileTransferException appears to be the replacement.

bergvdm’s picture

TransferException is part of the Guzzle library
use GuzzleHttp\Exception\TransferException

divya.lakshman’s picture

Hi team

After replacing

system_retrieve_file($url, $destination, $managed, $replace);

with

$data = (string) \Drupal::httpClient()->get($url)->getBody();
 return \Drupal::service('file.repository')->writeData($data, $destination, FileSystemInterface::EXISTS_REPLACE);

in my custom function , the $destination does not generate a proper output.

dafeder’s picture

The message here is pretty bizarre, neither of the two classes suggested as replacements exist in Drupal, and are not used in the sample code. Please consider editing this to avoid confusion.

richarddavies’s picture

I agree with @dafeder, the code sample contained several problems. I've updated the page to correct these issues.