Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough

Drupal 7, how to programmatically download files, optionally save them as managed files, save them to a node, and create directories at the same time!

Parent Feed: 

UPDATE:

Based on some comments below, I have updated the function with a sligtly more drupalesck approach. Thanks for the comments!

The previous version of this function had a bug where it would create a directory called public:/ in your webroot directory. Watch out, that being there can cause file upload problems. Make sure you delete that directory.

Recently I needed to write a universal function that would download files from a specified url and save them to a node. I also need directories to be progromatically created as well. Most of what I could find on the net was lacking a complete example. After a few hours banging my head against the wall, this is what I came up with.

/**
 *
 * 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
 */
function 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 {
    drupal_set_message("Could not create directory");
  }
}

Then to save to a node you just do the following

        $uri  =  'public://some_directory/new_1/file.txt';
        $new_file = download_external_file('http://www.somewebsite.com/somefile.txt', $uri, FILE_EXISTS_REPLACE);

        if($new_file) {
          $node->name_of_my_filefield[X][] = $new_file;
          node_save($node);
        } else {
          drupal_set_message("Download failed");
        }

That's it!

Author: 
Original Post: 

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web