Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

File API: Difference between revisions

From MoodleDocs
m (Update migration status and path)
 
(62 intermediate revisions by 23 users not shown)
Line 1: Line 1:
{{Template:Migrated|newDocId=/docs/apis/subsystems/files}}
{{Moodle 2.0}}
{{Moodle 2.0}}
The File API is for managing all the files stored by Moodle. If you are interested in how the file API works internally, see [[File API]]. The page is just about what you need to know to use the file API. Related is the [[Repository API]], which lets users get files into Moodle.
==Overview==
 
The File API is for managing all the files stored by Moodle. If you are interested in how the file API works internally, see [[File API internals]]. The page is just about what you need to know to use the file API. Related is the [[Repository API]], which lets users get files into Moodle.
 
If you are looking for an explanation on how to manage moodle files in moodle forms, you most likely need to read [[Using_the_File_API_in_Moodle_forms|Using the File API in Moodle forms]].


==File areas==
==File areas==


Files are are conceptually stored in '''file areas'''. A file area is uniquely identified by:
Files are conceptually stored in '''file areas'''. A file area is uniquely identified by:
* A context id.
* A context id.
* A file area type, for example 'course_intro' or 'forum_post'.
* full component name (using [[Frankenstyle]]), for example 'course', 'mod_forum', 'mod_glossary', 'block_html'.
* A unique itemid. Normally, the itemid relates to something depending on the file area type. For example, for a 'course_intro' file area, the itemid is is the course id. For forum post, it is the post id.
* A file area type, for example 'intro' or 'post'.
* A unique itemid. Normally, the itemid relates to something depending on the file area type. For example, for a 'course', 'intro' file area, the itemid is 0. For forum post, it is the post id.


File areas are not listed separately anywhere, they are stored implicitly in the files table. Please note that each subsystem is allowed to access only own file areas, for example core code must not access module or block files directly.
File areas are not listed separately anywhere, they are stored implicitly in the files table. Please note that each subsystem is allowed to access only own file areas, for example only code in /mod/assignment/* may access files with component 'mod_assignment'.


===Naming file areas===
===Naming file areas===


It is important that file areas are named consistently so we do not get name collisions, and so the names are easy to understand. Please follow the following guidelines:
The names of the file areas are not strictly defined, but it is strongly recommended to use singulars and common names of areas if possible (intro, post, attachment, description, ...).
 
==Serving files to users==
 
You must refer to the file with a URL that includes a file-serving script, often pluginfile.php. For example
 
The general form of the URL is something like
<syntaxhighlight lang="php">
$url = $CFG->wwwroot/pluginfile.php/$contextid/$component/$filearea/arbitrary/extra/infomation.ext
</syntaxhighlight>
 
A specific example might be
<syntaxhighlight lang="php">
$url = $CFG->wwwroot/pluginfile.php/$forumcontextid/mod_forum/post/$postid/image.jpg
</syntaxhighlight>


====start of the name====
Usually, you do not need to construct this URL directly - the function moodle_url::make_pluginfile_url() should be used instead:
<syntaxhighlight lang="php">
$url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(), $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename(), false);
</syntaxhighlight>
Note: If you do not need the 'itemid', then pass null in as this parameter and it will be entirely missed out from the URL - you need to take this into account when serving the file in the callback function, below.


If the file area belongs to a plugin, please use the plugin name as the start of the file area name.
The final parameter ('false' here) is 'forcedownload'.


This is the same plugin name that you would use for get_string calls. Some examples:
The file serving script then looks at the context id, and component name, and the file area name, and based on that arranges for the file to be served, following appropriate security checks.
* All file areas that belong to the forum modules should have a name beginning with 'forum'. For example 'forum_post', 'forum_intro'.
* A file area belonging to the HTML block would start 'block_html_'.
* A file area belonging to a question type would start 'qtype_myqtype_', except this is probably not necessary, because question type images should probably be stored in the core 'question_text' file area.
* If the file area is used by a local hack, the file area name should start 'local_'.


If the file area belongs to core code, the file area name should start with a prefix that indicates what part of Moodle it belongs to.
<strong>Note: </strong>In most cases, when developing third party plugins, pluginfile.php looks for a '''callback function''' in the appropriate plugin. These functions are stored in '''lib.php''' files and are named '''component_name_pluginfile()'''. The arbitrary/extra/infomation.ext is passed to the callback. For example, files in the mod_forum+post file area end up being served by the mod_forum_pluginfile function in mod/forum/lib.php. This function in MYPLUGIN/lib.php will usually follow a pattern like the example below, but the details will vary depending on the restrictions your plugin places on accessing different files (e.g. assignment files can only be accessed by teachers and the student who submitted the file, forum attachments require access to the discussion they are posted on):
<syntaxhighlight lang="php">
/**
* Serve the files from the MYPLUGIN file areas
*
* @param stdClass $course the course object
* @param stdClass $cm the course module object
* @param stdClass $context the context
* @param string $filearea the name of the file area
* @param array $args extra arguments (itemid, path)
* @param bool $forcedownload whether or not force download
* @param array $options additional options affecting the file serving
* @return bool false if the file not found, just send the file otherwise and do not return anything
*/
function MYPLUGIN_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
    // Check the contextlevel is as expected - if your plugin is a block, this becomes CONTEXT_BLOCK, etc.
    if ($context->contextlevel != CONTEXT_MODULE) {
        return false;
    }


But try to avoid clashing with prefixes that a plugin might use. Some examples:
    // Make sure the filearea is one of those used by the plugin.
* 'course_intro'
    if ($filearea !== 'expectedfilearea' && $filearea !== 'anotherexpectedfilearea') {
* 'question_text'
        return false;
* 'user_draft' (although draft file areas are a special case).
    }


====rest of the name====
    // Make sure the user is logged in and has access to the module (plugins that are not course modules should leave out the 'cm' part).
    require_login($course, true, $cm);


Like naming variables or functions, try to find a name that is short, but says exactly what the file area is for.
    // Check the relevant capabilities - these may vary depending on the filearea being accessed.
    if (!has_capability('mod/MYPLUGIN:view', $context)) {
        return false;
    }


If possible use the name of the file area to give a clue as to which database table the itemid relates to. For example:
    // Leave this line out if you set the itemid to null in make_pluginfile_url (set $itemid to 0 instead).
    $itemid = array_shift($args); // The first item in the $args array.
   
    // Use the itemid to retrieve any relevant data records and perform any security checks to see if the
    // user really does have access to the file in question.


* For the 'forum_post' file area, the itemid links to forum_post.id.
    // Extract the filename / filepath from the $args array.
* For 'question_text' file area, the itemid links to question.id. (Would it be permissible to call this file area just question?)
    $filename = array_pop($args); // The last item in the $args array.
    if (!$args) {
        $filepath = '/'; // $args is empty => the path is '/'
    } else {
        $filepath = '/'.implode('/', $args).'/'; // $args contains elements of the filepath
    }
 
    // Retrieve the file from the Files API.
    $fs = get_file_storage();
    $file = $fs->get_file($context->id, 'mod_MYPLUGIN', $filearea, $itemid, $filepath, $filename);
    if (!$file) {
        return false; // The file does not exist.
    }


==Serving files to users==
    // We can now send the file back to the browser - in this case with a cache lifetime of 1 day and no filtering.
    send_stored_file($file, 86400, 0, $forcedownload, $options);
}
</syntaxhighlight>


You must refer to the file with a URL that includes a file-serving script, often pluginfile.php. For example
You normally use an API function to generate these URL automatically, most often the <tt>file_rewrite_pluginfile_urls</tt> function.
<code php>
$url = $CFG->wwwroot/pluginfile.php/$contextid/$filearea/$itemid/file/path.ext;
</code>
Often you get these URLs generated automatically for you using the function file_rewrite_pluginfile_urls.


==Getting files from the user==
==Getting files from the user==


* See [[Using_the_File_API_in_Moodle_forms|Using the File API in Moodle forms]]
* See [[Using_the_File_API_in_Moodle_forms|Using the File API in Moodle forms]]
==Examples==
==Examples==
Please note that in reality developers outside of core will not deal with file api directly in majority of cases, instead use formslib elements which are doing all this automatically.
Please note that in reality developers outside of core will not deal with file api directly in majority of cases, instead use formslib elements which are doing all this automatically.


===Browsing files===
===Browsing files===
<code php>
<syntaxhighlight lang="php">
$browser = get_file_browser();
$browser = get_file_browser();
$context = get_system_context();
$context = get_system_context();
Line 63: Line 121:
$itemid  = null;
$itemid  = null;
$filename = null;
$filename = null;
if ($fileinfo = $browser->get_file_info($context, $filearea, $itemid, '/', $filename)) {
if ($fileinfo = $browser->get_file_info($context, $component, $filearea, $itemid, '/', $filename)) {
     // build a Breadcrumb trail
     // build a Breadcrumb trail
     $level = $fileinfo->get_parent();
     $level = $fileinfo->get_parent();
     while ($level) {
     while ($level) {
        $params = base64_encode(serialize($level->get_params()));
         $path[] = array('name'=>$level->get_visible_name());
         $path[] = array('name'=>$level->get_visible_name(), 'path'=>$params);
         $level = $level->get_parent();
         $level = $level->get_parent();
     }
     }
Line 76: Line 133:
         if ($child->is_directory()) {
         if ($child->is_directory()) {
             echo $child->get_visible_name();
             echo $child->get_visible_name();
             // display contextid, itemid, filepath and filename
             // display contextid, itemid, component, filepath and filename
             var_dump($child->get_params());
             var_dump($child->get_params());
         }
         }
Line 82: Line 139:
}
}


</code>
</syntaxhighlight>
 
===Moving files around===
===Moving files around===


For example, if you have just built a file at the path
For example, if you have just built a file at the path
<code php>
<syntaxhighlight lang="php">
  $from_zip_file = $CFG->dataroot . '/temp/backup/' . $preferences->backup_unique_code .
  $from_zip_file = $CFG->dataroot . '/temp/backup/' . $preferences->backup_unique_code .
         '/' . $preferences->backup_name;
         '/' . $preferences->backup_name;
</code>
</syntaxhighlight>
And you want to move it into the course_backup file area, do
And you want to move it into the course_backup file area, do
<code php>
<syntaxhighlight lang="php">
  $context = get_context_instance(CONTEXT_COURSE, $preferences->backup_course);
  $context = get_context_instance(CONTEXT_COURSE, $preferences->backup_course);
  $fs = get_file_storage();
  $fs = get_file_storage();
  $file_record = array('contextid'=>$context->id, 'filearea'=>'course_backup',
  $file_record = array('contextid'=>$context->id, 'component'=>'course', 'filearea'=>'backup',
         'itemid'=>0, 'filepath'=>'/', 'filename'=>$preferences->backup_name,
         'itemid'=>0, 'filepath'=>'/', 'filename'=>$preferences->backup_name,
         'timecreated'=>time(), 'timemodified'=>time());
         'timecreated'=>time(), 'timemodified'=>time());
  $fs->create_file_from_pathname($file_record, $from_zip_file);
  $fs->create_file_from_pathname($file_record, $from_zip_file);
</code>
</syntaxhighlight>
===Create a copy of stored file===
If you need to create a copy of stored file (actually, it add a new record in database):
<code php>
$context  = get_context_instance_by_id($contextid);
$file_info = $browser->get_file_info($context, $filearea, $fileitemid, $filepath, $filename);
// copy this file to draft area
$file_info->copy_to_storage($user_context->id, 'user_draft', $newitemid, '/', $title);
</code>


=== List area files ===
=== List area files ===
<code php>
<syntaxhighlight lang="php">
$fs = get_file_storage();
$fs = get_file_storage();
$files = $fs->get_area_files($contextid, 'user_draft');
$files = $fs->get_area_files($contextid, 'mod_assignment', 'submission', $submission->id);
foreach ($files as $f) {
foreach ($files as $f) {
     // $f is an instance of stored_file
     // $f is an instance of stored_file
     echo $f->get_filename();
     echo $f->get_filename();
}
}
</code>
</syntaxhighlight>
 
Or as links...
 
<syntaxhighlight lang="php">
$out = array();
       
$fs = get_file_storage();
$files = $fs->get_area_files($contextid, 'mod_assignment', 'submission', $submission->id);
           
foreach ($files as $file) {
    $filename = $file->get_filename();
    $url = moodle_url::make_file_url('/pluginfile.php', array($file->get_contextid(), 'mod_assignment', 'submission',
            $file->get_itemid(), $file->get_filepath(), $filename));
    $out[] = html_writer::link($url, $filename);
}
$br = html_writer::empty_tag('br');
       
return implode($br, $out);
</syntaxhighlight>
 
=== Create file ===
 
Here's how to create a file whose contents will be a text string. This is the equivalent of the PHP function <tt>file_put_contents</tt>.
 
<syntaxhighlight lang="php">
$fs = get_file_storage();
 
// Prepare file record object
$fileinfo = array(
    'contextid' => $context->id, // ID of context
    'component' => 'mod_mymodule',    // usually = table name
    'filearea' => 'myarea',    // usually = table name
    'itemid' => 0,              // usually = ID of row in table
    'filepath' => '/',          // any path beginning and ending in /
    'filename' => 'myfile.txt'); // any filename
 
// Create file containing text 'hello world'
$fs->create_file_from_string($fileinfo, 'hello world');
</syntaxhighlight>
 
If you want to create a file in the Moodle file area based on a 'real' file e.g. in a temporary folder, you can use <tt>create_file_from_pathname</tt> instead. Similarly, you can create a file based on some other file already in Moodle's local files by using <tt>create_file_from_storedfile</tt>. Browse through <tt>lib/filestorage/file_storage.php</tt> for details.
 
Unlike with ordinary files, this method will not automatically overwrite an existing file. If you wish to overwrite a file, you must first get the file and (if it exists) delete it, and only then create it again.
 
=== Read file ===
 
This is a way to read a file, equivalent to <tt>file_get_contents</tt>. '''Please note your are allowed to do this ONLY from mod/mymodule/* code, it is not acceptable to do this anywhere else.''' Other code has to use file_browser interface instead.
 
<syntaxhighlight lang="php">
$fs = get_file_storage();
 
// Prepare file record object
$fileinfo = array(
    'component' => 'mod_mymodule',    // usually = table name
    'filearea' => 'myarea',    // usually = table name
    'itemid' => 0,              // usually = ID of row in table
    'contextid' => $context->id, // ID of context
    'filepath' => '/',          // any path beginning and ending in /
    'filename' => 'myfile.txt'); // any filename
 
// Get file
$file = $fs->get_file($fileinfo['contextid'], $fileinfo['component'], $fileinfo['filearea'],
                      $fileinfo['itemid'], $fileinfo['filepath'], $fileinfo['filename']);
 
// Read contents
if ($file) {
    $contents = $file->get_content();
} else {
    // file doesn't exist - do something
}
</syntaxhighlight>
 
If you want to access the file directly on disk, this is not permitted. Instead, you need to make a copy of the file in a temporary area and use that. You can do this with <tt>$file->copy_content_to($pathname)</tt>.
 
=== Delete file ===
 
<syntaxhighlight lang="php">
$fs = get_file_storage();
 
// Prepare file record object
$fileinfo = array(
    'component' => 'mod_mymodule',
    'filearea' => 'myarea',    // usually = table name
    'itemid' => 0,              // usually = ID of row in table
    'contextid' => $context->id, // ID of context
    'filepath' => '/',          // any path beginning and ending in /
    'filename' => 'myfile.txt'); // any filename
 
// Get file
$file = $fs->get_file($fileinfo['contextid'], $fileinfo['component'], $fileinfo['filearea'],
        $fileinfo['itemid'], $fileinfo['filepath'], $fileinfo['filename']);
 
// Delete it if it exists
if ($file) {
    $file->delete();
}
</syntaxhighlight>
 
=== Convert between file formats (office documents) ===
{{Moodle 3.1}}
 
This functionality requires "unoconv" to be installed and configured on the site - so it is not available on all installations.
 
<syntaxhighlight lang="php">
$fs = get_file_storage();
 
// Prepare file record object
$fileinfo = array(
    'component' => 'mod_mymodule',
    'filearea' => 'myarea',    // usually = table name
    'itemid' => 0,              // usually = ID of row in table
    'contextid' => $context->id, // ID of context
    'filepath' => '/',          // any path beginning and ending in /
    'filename' => 'myfile.txt'); // any filename
 
// Get file
$file = $fs->get_file($fileinfo['contextid'], $fileinfo['component'], $fileinfo['filearea'],
        $fileinfo['itemid'], $fileinfo['filepath'], $fileinfo['filename']);
 
// Try and convert it if it exists
if ($file) {
    $convertedfile = $fs->get_converted_document($file, 'pdf');
}
</syntaxhighlight>


==See also==
==See also==


* [[File API]] how the File API works internally.
* [[Core APIs]]
* [[Roadmap|Moodle 2.0 roadmap]]
* [[File API internals]] how the File API works internally.
* [[Using the File API in Moodle forms]]




[[Category:Files]]
[[Category:Files]]
[[Category:API]]

Latest revision as of 01:41, 24 May 2022

Important:

This content of this page has been updated and migrated to the new Moodle Developer Resources. The information contained on the page should no longer be seen up-to-date.

Why not view this page on the new site and help us to migrate more content to the new site!

Moodle 2.0


Overview

The File API is for managing all the files stored by Moodle. If you are interested in how the file API works internally, see File API internals. The page is just about what you need to know to use the file API. Related is the Repository API, which lets users get files into Moodle.

If you are looking for an explanation on how to manage moodle files in moodle forms, you most likely need to read Using the File API in Moodle forms.

File areas

Files are conceptually stored in file areas. A file area is uniquely identified by:

  • A context id.
  • full component name (using Frankenstyle), for example 'course', 'mod_forum', 'mod_glossary', 'block_html'.
  • A file area type, for example 'intro' or 'post'.
  • A unique itemid. Normally, the itemid relates to something depending on the file area type. For example, for a 'course', 'intro' file area, the itemid is 0. For forum post, it is the post id.

File areas are not listed separately anywhere, they are stored implicitly in the files table. Please note that each subsystem is allowed to access only own file areas, for example only code in /mod/assignment/* may access files with component 'mod_assignment'.

Naming file areas

The names of the file areas are not strictly defined, but it is strongly recommended to use singulars and common names of areas if possible (intro, post, attachment, description, ...).

Serving files to users

You must refer to the file with a URL that includes a file-serving script, often pluginfile.php. For example

The general form of the URL is something like

$url = $CFG->wwwroot/pluginfile.php/$contextid/$component/$filearea/arbitrary/extra/infomation.ext

A specific example might be

$url = $CFG->wwwroot/pluginfile.php/$forumcontextid/mod_forum/post/$postid/image.jpg

Usually, you do not need to construct this URL directly - the function moodle_url::make_pluginfile_url() should be used instead:

$url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(), $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename(), false);

Note: If you do not need the 'itemid', then pass null in as this parameter and it will be entirely missed out from the URL - you need to take this into account when serving the file in the callback function, below.

The final parameter ('false' here) is 'forcedownload'.

The file serving script then looks at the context id, and component name, and the file area name, and based on that arranges for the file to be served, following appropriate security checks.

Note: In most cases, when developing third party plugins, pluginfile.php looks for a callback function in the appropriate plugin. These functions are stored in lib.php files and are named component_name_pluginfile(). The arbitrary/extra/infomation.ext is passed to the callback. For example, files in the mod_forum+post file area end up being served by the mod_forum_pluginfile function in mod/forum/lib.php. This function in MYPLUGIN/lib.php will usually follow a pattern like the example below, but the details will vary depending on the restrictions your plugin places on accessing different files (e.g. assignment files can only be accessed by teachers and the student who submitted the file, forum attachments require access to the discussion they are posted on):

/**
 * Serve the files from the MYPLUGIN file areas
 *
 * @param stdClass $course the course object
 * @param stdClass $cm the course module object
 * @param stdClass $context the context
 * @param string $filearea the name of the file area
 * @param array $args extra arguments (itemid, path)
 * @param bool $forcedownload whether or not force download
 * @param array $options additional options affecting the file serving
 * @return bool false if the file not found, just send the file otherwise and do not return anything
 */
function MYPLUGIN_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
    // Check the contextlevel is as expected - if your plugin is a block, this becomes CONTEXT_BLOCK, etc.
    if ($context->contextlevel != CONTEXT_MODULE) {
        return false; 
    }

    // Make sure the filearea is one of those used by the plugin.
    if ($filearea !== 'expectedfilearea' && $filearea !== 'anotherexpectedfilearea') {
        return false;
    }

    // Make sure the user is logged in and has access to the module (plugins that are not course modules should leave out the 'cm' part).
    require_login($course, true, $cm);

    // Check the relevant capabilities - these may vary depending on the filearea being accessed.
    if (!has_capability('mod/MYPLUGIN:view', $context)) {
        return false;
    }

    // Leave this line out if you set the itemid to null in make_pluginfile_url (set $itemid to 0 instead).
    $itemid = array_shift($args); // The first item in the $args array.
    
    // Use the itemid to retrieve any relevant data records and perform any security checks to see if the
    // user really does have access to the file in question.

    // Extract the filename / filepath from the $args array.
    $filename = array_pop($args); // The last item in the $args array.
    if (!$args) {
        $filepath = '/'; // $args is empty => the path is '/'
    } else {
        $filepath = '/'.implode('/', $args).'/'; // $args contains elements of the filepath
    }

    // Retrieve the file from the Files API.
    $fs = get_file_storage();
    $file = $fs->get_file($context->id, 'mod_MYPLUGIN', $filearea, $itemid, $filepath, $filename);
    if (!$file) {
        return false; // The file does not exist.
    }

    // We can now send the file back to the browser - in this case with a cache lifetime of 1 day and no filtering. 
    send_stored_file($file, 86400, 0, $forcedownload, $options);
}

You normally use an API function to generate these URL automatically, most often the file_rewrite_pluginfile_urls function.

Getting files from the user

Examples

Please note that in reality developers outside of core will not deal with file api directly in majority of cases, instead use formslib elements which are doing all this automatically.

Browsing files

$browser = get_file_browser();
$context = get_system_context();

$filearea = null;
$itemid   = null;
$filename = null;
if ($fileinfo = $browser->get_file_info($context, $component, $filearea, $itemid, '/', $filename)) {
    // build a Breadcrumb trail
    $level = $fileinfo->get_parent();
    while ($level) {
        $path[] = array('name'=>$level->get_visible_name());
        $level = $level->get_parent();
    }
    $path = array_reverse($path);
    $children = $fileinfo->get_children();
    foreach ($children as $child) {
        if ($child->is_directory()) {
            echo $child->get_visible_name();
            // display contextid, itemid, component, filepath and filename
            var_dump($child->get_params());
        }
    }
}

Moving files around

For example, if you have just built a file at the path

 $from_zip_file = $CFG->dataroot . '/temp/backup/' . $preferences->backup_unique_code .
         '/' . $preferences->backup_name;

And you want to move it into the course_backup file area, do

 $context = get_context_instance(CONTEXT_COURSE, $preferences->backup_course);
 $fs = get_file_storage();
 $file_record = array('contextid'=>$context->id, 'component'=>'course', 'filearea'=>'backup',
         'itemid'=>0, 'filepath'=>'/', 'filename'=>$preferences->backup_name,
         'timecreated'=>time(), 'timemodified'=>time());
 $fs->create_file_from_pathname($file_record, $from_zip_file);

List area files

$fs = get_file_storage();
$files = $fs->get_area_files($contextid, 'mod_assignment', 'submission', $submission->id);
foreach ($files as $f) {
    // $f is an instance of stored_file
    echo $f->get_filename();
}

Or as links...

$out = array();
        
$fs = get_file_storage();
$files = $fs->get_area_files($contextid, 'mod_assignment', 'submission', $submission->id);
            
foreach ($files as $file) {
    $filename = $file->get_filename();
    $url = moodle_url::make_file_url('/pluginfile.php', array($file->get_contextid(), 'mod_assignment', 'submission',
            $file->get_itemid(), $file->get_filepath(), $filename));
    $out[] = html_writer::link($url, $filename);
}
$br = html_writer::empty_tag('br');
        
return implode($br, $out);

Create file

Here's how to create a file whose contents will be a text string. This is the equivalent of the PHP function file_put_contents.

$fs = get_file_storage();

// Prepare file record object
$fileinfo = array(
    'contextid' => $context->id, // ID of context
    'component' => 'mod_mymodule',     // usually = table name
    'filearea' => 'myarea',     // usually = table name
    'itemid' => 0,               // usually = ID of row in table
    'filepath' => '/',           // any path beginning and ending in /
    'filename' => 'myfile.txt'); // any filename

// Create file containing text 'hello world'
$fs->create_file_from_string($fileinfo, 'hello world');

If you want to create a file in the Moodle file area based on a 'real' file e.g. in a temporary folder, you can use create_file_from_pathname instead. Similarly, you can create a file based on some other file already in Moodle's local files by using create_file_from_storedfile. Browse through lib/filestorage/file_storage.php for details.

Unlike with ordinary files, this method will not automatically overwrite an existing file. If you wish to overwrite a file, you must first get the file and (if it exists) delete it, and only then create it again.

Read file

This is a way to read a file, equivalent to file_get_contents. Please note your are allowed to do this ONLY from mod/mymodule/* code, it is not acceptable to do this anywhere else. Other code has to use file_browser interface instead.

$fs = get_file_storage();

// Prepare file record object
$fileinfo = array(
    'component' => 'mod_mymodule',     // usually = table name
    'filearea' => 'myarea',     // usually = table name
    'itemid' => 0,               // usually = ID of row in table
    'contextid' => $context->id, // ID of context
    'filepath' => '/',           // any path beginning and ending in /
    'filename' => 'myfile.txt'); // any filename

// Get file
$file = $fs->get_file($fileinfo['contextid'], $fileinfo['component'], $fileinfo['filearea'],
                      $fileinfo['itemid'], $fileinfo['filepath'], $fileinfo['filename']);

// Read contents
if ($file) {
    $contents = $file->get_content();
} else {
    // file doesn't exist - do something
}

If you want to access the file directly on disk, this is not permitted. Instead, you need to make a copy of the file in a temporary area and use that. You can do this with $file->copy_content_to($pathname).

Delete file

$fs = get_file_storage();

// Prepare file record object
$fileinfo = array(
    'component' => 'mod_mymodule',
    'filearea' => 'myarea',     // usually = table name
    'itemid' => 0,               // usually = ID of row in table
    'contextid' => $context->id, // ID of context
    'filepath' => '/',           // any path beginning and ending in /
    'filename' => 'myfile.txt'); // any filename

// Get file
$file = $fs->get_file($fileinfo['contextid'], $fileinfo['component'], $fileinfo['filearea'], 
        $fileinfo['itemid'], $fileinfo['filepath'], $fileinfo['filename']);

// Delete it if it exists
if ($file) {
    $file->delete();
}

Convert between file formats (office documents)

Moodle 3.1


This functionality requires "unoconv" to be installed and configured on the site - so it is not available on all installations.

$fs = get_file_storage();

// Prepare file record object
$fileinfo = array(
    'component' => 'mod_mymodule',
    'filearea' => 'myarea',     // usually = table name
    'itemid' => 0,               // usually = ID of row in table
    'contextid' => $context->id, // ID of context
    'filepath' => '/',           // any path beginning and ending in /
    'filename' => 'myfile.txt'); // any filename

// Get file
$file = $fs->get_file($fileinfo['contextid'], $fileinfo['component'], $fileinfo['filearea'], 
        $fileinfo['itemid'], $fileinfo['filepath'], $fileinfo['filename']);

// Try and convert it if it exists
if ($file) {
    $convertedfile = $fs->get_converted_document($file, 'pdf');
}

See also