7

I am programmatically importing images and saving them via file_save_data();

$fileContentsPath = 'http://mypathtofile.com';
$uri = 'public://myfolder/mysecondfolder/filename.jpg';
$image = file_get_contents($fileContentsPath);
$file = file_save_data($image, $uri, FILE_EXISTS_REPLACE);

When I run this I get the following error: The specified file temporary://fileJ4LL4o could not be copied, because the destination directory is not properly configured. This may be caused by a problem with file or directory permissions. More information is available in the system log.

I am pretty sure my temporary directory is configured correctly and the files folder is assigned to the apache user.

If I go into the files directory and make the directories (myfolder/mysecondfolder) via command line and rerun it works correctly.

So the problem is that if the folders don't exist from the $uri path, it fails instead of creating the folders.

3 Answers 3

9

In drupal 8.7.0 and above (Drupal 9), file_prepare_directory() is deprecated.

Instead, use FileSystemInterface::prepareDirectory() : https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21File%21FileSystemInterface.php/function/FileSystemInterface%3A%3AprepareDirectory/8.8.x

In my case, I did :

/** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system');
$directory = 'temporary://exports/';
$file_system->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY);
8

I Noticed Similar issue while saving files using

 file_save_data();

In Drupal 8.

First I gave only first level directory to save the file as

$file = file_save_data($object->vertex_data, 'public://vertex_data.txt', FILE_EXISTS_REPLACE);

This worked fine.

But when I tried saving the file inside a subfolder as

$file = file_save_data($object->vertex_data, 'public://objects/vertex_data.txt', FILE_EXISTS_REPLACE);

it gave me the following Error :

File temporary://fileh1Gpl2 could not be moved/copied because the destination directory public://objects/ is not configured correctly.

The Solution for this is simple. Just use file_prepare_directory();

$directory = 'public://objects/'
file_prepare_directory($directory, FILE_CREATE_DIRECTORY);
$file = file_save_data($object->vertex_data,  $directory . 'vertex_data.txt', FILE_EXISTS_REPLACE);

This, first creates the folder if it does not exists and then proceeds to save the respective file.

2

I ended up using a function that creates the folders if needed. I copied what Patrick had here.

/**
 * Download external file.
 *
 * @param string $url       Full url to file to download.
 * @param string $uri       Drupal uri of where to save file
 *                          public://archive/test.pdf.
 * @param int $save_mode    File save mode from drupal core
 *                          Ex: FILE_EXISTS_REPLACE.
 *
 * @return mixed $new_file  The file object.
 */
function xcms_import_download_external_file($url, $uri, $save_mode = FILE_EXISTS_RENAME, $manage_file = TRUE) {

  $url_info = parse_url($url);
  $url_path_info = pathinfo($url_info['path']);

  // This helps with filenames with spaces
  $url = $url_info['scheme'] . '://' . $url_info['host']  . $url_path_info['dirname'] .'/'. rawurlencode($url_path_info['basename']);

  // Need to remove the filename from the uri
  $uri_target = file_uri_target($uri);
  $uri_scheme = file_uri_scheme($uri);
  $uri_path_info = pathinfo($uri_target);
  $directory = file_stream_wrapper_uri_normalize($uri_scheme . "://" . $uri_path_info['dirname']);

  if (file_prepare_directory($directory, FILE_CREATE_DIRECTORY)) {
    $drupal_result = drupal_http_request($url);
    if (!empty($drupal_result->data)) {
      $path = file_stream_wrapper_uri_normalize($uri);
      if ($manage_file) {
        $new_file = file_save_data($drupal_result->data, $path, $save_mode);
      }
      else {
        return file_unmanaged_save_data($drupal_result->data, $path, $save_mode);
      }
    }
    else {
      drupal_set_message("Error downloading file, no data recieved for " . $url);
      return FALSE;
    }

    $new_file->display = 1;
    return (array)$new_file;
  }
  else {
    return FALSE;
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.