Programmatically Insert Local Files to Managed Files

Wed 22nd Feb 2012 -- Nick Schuch

As numerous posts out there state, this is the way to programmatically add files into Drupal 7's file module tables.

<?php
// Load the files contents
$image = file_get_contents(<path to file>);

// Returns the new file object
$file = file_save_data($image, 'public://<filename>', FILE_EXISTS_RENAME);
?>

However after working on the module CCTV (Currently getting approval for Full Project) I found that this was not enough.

For some background details, CCTV is a module that turns your Drupal site into a IP Camera capture application. Based on the users preference the application can save files up to 1 day in file size (which equates to a very large file). Due to the large file sizes generated by CCTV php runs into memory both max file php configuration and local allocated memory issues. So how do we get around this?

After digging through the file modules documentation I found the following solution.

<?php
$handle
= fopen('<path to local file>', 'r');
$file = file_save_data($handle, 'public://<filename>');
fclose($handle);
?>

This opens the file in read only mode and using the file module's function file_save_data it copies the file to the public:// file system. This not only makes your code more efficient, but also allows for bypassing around php's max file size constraints.

Category: 

Comments

Submitted by yakoub on

function mymodule_move_file($file) {
  $file->filename = basename($file->filepath);
  unset($file->filepath);
  $file_path = 'source/' . $file->filename;
  $dest = 'images/' . $file->filename;
  $file->uid =1;
  $file->status = FILE_STATUS_PERMANENT;
  $file->uri = file_build_uri($file_path);
  if (!file_exists($file->uri)) {
    error_log('filemove:' . $file_path);
    return NULL;
  }
  return file_move($file, file_build_uri($dest) );
}

Submitted by david g. on

the authors code simply reads the file contents from anywhere and places it in drupal's /files directory.
D7 file_move() deletes the source file by default if possible -- that may be an unwanted behavior. I also thought some of the drupal file commands work only from within drupals webroot, the author is moving files from anywhere on disk it looks like.

Nick Schuch's picture
Submitted by Nick Schuch on

Exactly. Fewer lines of code and can access the servers files from outside of the webroot directory. Looking through the code of file_save_data it calls also file_unmanaged_move. In this case however, I am opening the local file with read-only permissions which negates the move.

Submitted by Anonymous on

The file API only guarantees to work with string $data.

You are relying on an implementation detail of file_save_data, i.e. that it calls file_save_unmanaged_data which in turn uses file_put_contents($name, $data) to actually do the writing. Because the latter supports stream resources, this all works. For now.

Submitted by Uwe on

For an import job I will already have the file in the files directory. How would I save the name to file_managed?

Add new comment

Filtered HTML

  • To post pieces of code, surround them with <code>...</code> tags. For PHP code, you can use <?php ... ?>, which will also colour it based on syntax.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd><div>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.