首页 > 代码库 > Moodle 中文 API 之 文件管理API

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();
}

 













Moodle 中文 API 之 文件管理API