Moodle 中文 API 之 文件管理API
File API 文件管理
文件夹
1. 概述
2. 文件域
2.1 命名文件域
3. 提供文件给用户
4. 从用户那获取文件
5. 样例
5.1 浏览文件
5.2 移动文件
5.3 文件列表
5.4创建文件
5.5 读文件
5.6 删除文件
1. 概述
文件 API 是讲述在Moodle中的全部的文件存储. 假设你对文件怎样工作感兴趣,请到官网查看File API internals. 这篇文章不过告诉你知道怎样使用 file API.与之相关的是Repository API(让用户从moodle获取文件)
假设你想知道怎样管理文件在moodle 表单中, 你最好在去官网阅读 Using the File API in Moodle forms.
2. 文件域
文件被保存在file areas. 一个文件域被唯一定义通过例如以下:
· 一个 context id.
· 完整的component 名字 (使用 Frankenstyle), 比如 'course', 'mod_forum', 'mod_glossary', 'block_html'.
· 一个文件域类型(type), 比如 'intro' 或 'post'.
· 一个唯一的 itemid. 一般的, 这个 itemid 会依赖文件域类型. 比如, 对于 'course', 'intro' 文件域, 那么itemid 就是 0. 对于 forum post, 那就是它的 post id.
文件域并非分散的到处都是, 它们存储在 files 表里. 请注意每个子系统仅仅能訪问自己的文件域, 比如代码放在 /mod/assignment/* 仅仅能訪问component名为 'mod_assignment'.的文件。
2.1 命名文件域
文件域的名字不是严格定义的, 可是强烈推荐你使用具有标志意思的名字 如(intro, post, attachment, description, ...).
3. 提供文件给用户
你必须使用包括一个 file-serving 脚本的文件URL , 一般是 pluginfile.php. 比如:一般 URL 的形式像这样:
$url = $CFG->wwwroot/pluginfile.php/$contextid/$component/$filearea/arbitrary/extra/infomation.ext
特殊一点的可能像这样
$url = $CFG->wwwroot/pluginfile.php/$forumcontextid/mod_forum/post/$postid/image.jpg
通常你能够使用函数moodle_url::make_pluginfile_url()自己主动生成URL
$url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(), $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename());
注意: 假设你不须要 'itemid', 请填入空他将会在 URL中被忽略 - 你必须提供它在提供提供文件的回调函数里.例如以下
文件服务脚本会查看context id, 和 component 名字, 以及 file area 名字和文件的分配及安全检查.
注意:非常多时候, 当开发第三方插件时, pluginfile.php 被看做是一个回调函数在合适的插件里. 这里函数存放在lib.php 文件中 且命名为 component_name_pluginfile().这些 arbitrary/extra/infomation.ext 是通过回调生成的. 比如, 文件存在 mod_forum+post 文件域(file area) 那么为他提供服务的是 mod_forum_pluginfile 函数 在 mod/forum/lib.php.这个函数在 MYPLUGIN/lib.php 中一般会成对出现像以下的样例, 详细訪问权限还要依赖插件所处的位置 (比如. assignment 文件仅仅能让老师訪问学生提交的文件, forum attachments 须要通过discussion 提交上来的文件):
function MYPLUGIN_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { // 检查上下文级别是否是期望的 - 假设你的插件是一个块, 它就会变成 CONTEXT_BLOCK, 等. if ($context->contextlevel != CONTEXT_MODULE) { return false; } // 确保 filearea 是插件中的一个. if ($filearea !== 'expectedfilearea' && $filearea !== 'anotherexpectedfilearea') { return false; } // 确保用户是登陆的且有訪问这个模块的权限 (插件不是课程模块的能够忽略'cm' 部分). require_login($course, true, $cm); // 检查相关权限- 这些可能依赖于 filearea 是否能被訪问. if (!has_capability('mod/MYPLUGIN:view', $context)) { return false; } // 假设你设置 itemid为空的话。就忽略以下这行, make_pluginfile_url (设置$itemid为0 取代). $itemid = array_shift($args); // 參数数组中的第一个參数. // 使用 itemid 不论什么相关的数据记录 和不论什么安全检查,假设用户的确有訪问权限 // 额外的 filename / filepath 来自參数数组. $filename = array_pop($args); // 參数数组最后一个參数. if (!$args) { $filepath = '/'; // 參数为空时路径为 '/' } else { $filepath = '/'.implode('/', $args).'/'; // 參数包括文件路径的元素 } // 从文件API中遍历文件元素. $fs = get_file_storage(); $file = $fs->get_file($context->id, 'mod_MYPLUGIN', $filearea, $itemid, $filepath, $filename); if (!$file) { return false; // 这个文件不存在 } // 我们如今发送文件给浏览者- 这会有一个环新村生命周期 1 天 且不会过滤. // 从Moodle 2.3以后, 使用send_stored_file取代. send_file($file, 86400, 0, $forcedownload, $options);
你常常会用一个 API 去自己主动生成URL, 常常file_rewrite_pluginfile_urls函数.
3. 从用户那获取文件
在官网上查看 Using the File API in Moodle forms
5. 样例
远离核心代码的开发并不真正使用文件API,而是使用formslib取代他们自己主动完毕.
5.1 浏览文件
$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)) { // 建立一个面包屑 $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(); // 显示 contextid, itemid, component, filepath 和 filename var_dump($child->get_params()); } } }
5.2 移动文件
比如, 假设你只建立一个文件在暂时路径里
$from_zip_file = $CFG->dataroot . '/temp/backup/' . $preferences->backup_unique_code . '/' . $preferences->backup_name;
并且你想将他移动到course_backup 文件域, 那么你须要需做
$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);
5.3 文件列表
$fs = get_file_storage(); $files = $fs->get_area_files($contextid, 'mod_assignment', 'submission', $submission->id); foreach ($files as $f) { // $f 是stored_file的一个实例 echo $f->get_filename(); }
或者像链接...
$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);
5.4 创建文件
这儿介绍了怎样创建一个文本字符串文件. 相当于 PHP 函数file_put_contents.
$fs = get_file_storage(); // 准备文件记录对象 $fileinfo = array( 'contextid' => $context->id, // context的ID 'component' => 'mod_mymodule', // 模块名 'filearea' => 'myarea', // 文件域 'itemid' => 0, // usually = ID of row in table 'filepath' => '/', // 文件路径的開始和结束使用 / 'filename' => 'myfile.txt'); // 文件名称 // 创建包括文本'hello world'的文件 $fs->create_file_from_string($fileinfo, 'hello world');
假设你想创建一个文件在Moodle file area中基于一个真的文件。如.暂时的文件夹中,你能用create_file_from_pathname取代. 类似的,你能创建一个其它已经存在于 Moodle的本地文件通过使用 create_file_from_storedfile. 浏览通过lib/filestorage/file_storage.php 获取详细信息.
不同与普通文件, 这种方法不会自己主动重写一个存在的文件. 假设你希望重写一个文件, 你首先得获取这个文件删除它 (假设它存在的话),然后再次创建他.
5.5 读文件
这是读文件的一种方式, 等价于file_get_contents.请注意你只被同意訪问来自 mod/mymodule/* 模块的代码, 他是不能在其它不论什么地方訪问的. 其它代码不得不使用 file_browser接口取代.
$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 // 获取 $file = $fs->get_file($fileinfo['contextid'], $fileinfo['component'], $fileinfo['filearea'], $fileinfo['itemid'], $fileinfo['filepath'], $fileinfo['filename']); // 读取内容 if ($file) { $contents = $file->get_content(); } else { // 文件不存在时 代码 }
假设你想直接从硬盘訪问这个文件, 他是禁止的.你能够在暂时文件夹中得导一份拷贝.像这样 $file->copy_content_to($pathname),然后就能够訪问了.
5.6 删除文件
$fs = get_file_storage(); // 准备文件记录对象 $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'); // 文件名称 // 获取文件 $file = $fs->get_file($fileinfo['contextid'], $fileinfo['component'], $fileinfo['filearea'], $fileinfo['itemid'], $fileinfo['filepath'], $fileinfo['filename']); // 假设存在删除它 if ($file) { $file->delete(); }