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

}

时间: 2024-10-15 06:58:12

Moodle 中文 API 之 文件管理API的相关文章

Moodle 中文API之 全局输出API(一)

Output API 全局输出API (注:此API官方更新少,部分内容可能过时.) 目录 1. 组件 1.1 moodle_html_component  html组件 1.2 低级HTML 组件 1.2.1 html_label 1.2.2 html_field 1.2.3 html_button 1.2.4 action_link 1.2.5 html_img 1.2.6 html_form 1.2.7 html_list 1.2.8 html_list_item 1.2.9 html_t

moodle中文API之表单API

Form API 表单API 目录 1.概述 2.亮点 3.用法 4.表单元素 4.1 基本表单元素 4.2 定制表单元素 5.常用函数 5.1  add_action_buttons($cancel =true,$submitlabel =null) 5.2 setDefault() 5.3 disableif() 5.4 addRule() 5.5 setHelpButton 5.6 addHelpButton 5.7 setType() 5.8 disable_form_change_ch

读取中文的标准C API

这个是在Linux下遇到的,以前从来都不需要支持中文,最近项目需要. FILE *fp=NULL; fgets(buf, sizeof buf, fp); printf ("buf=%s\n", buf); 成功,就这样就满足我的需求了. 之前的弯路是fread()来读取,这个就太麻烦了,所以换了算法. 读取中文的标准C API

通过beego快速创建一个Restful风格API项目及API文档自动化(转)

通过beego快速创建一个Restful风格API项目及API文档自动化 本文演示如何快速(一分钟内,不写一行代码)的根据数据库及表创建一个Restful风格的API项目,及提供便于在线测试API的界面. 一.创建数据库及数据表(MySQL) #db--jeedev -- ---------------------------- -- Table structure for `app` -- ---------------------------- DROP TABLE IF EXISTS `a

LwIP - raw/callback API、协议栈API(sequential API)、BSD API(或者说 SOCKET API)

1.使用raw/callback API编程,用户编程的方法是向内核注册各种自定义的回调函数,回调函数是与内核实现交换的唯一方式. recv_udp, accept_function, sent_tcp, recv_tcp, do_connected, poll_tcp, err_tcp! 2.协议栈API(sequential API)是基于raw/callback API实现的,它与内核交换的方式也只能通过回调. netconn_new, netconn_delete, netconn_ge

关于CUDA两种API:Runtime API 和 Driver API

CUDA 眼下有两种不同的 API:Runtime API 和 Driver API,两种 API 各有其适用的范围. 高级API(cuda_runtime.h)是一种C++风格的接口,构建于低级API之上.因为 runtime API 较easy使用,一開始我们会以 runetime API 为主:

用API网关把API管起来

最开始只是想找个API网关防止API被恶意请求,找了一圈发现基于Nginx的OpenResty(Lua语言)扩展模块Orange挺好(也找了Kong,但是感觉复杂了点没用),还偷懒用Vagrant结合Docker来快速搭建环境,基于别人的Dockerfile把整个实验跑通了,觉得还不错.想着好像CoreOS是专门为Docker服务的,还买了一本<CoreOS实践>花小半天时间看完了,CoreOS在集群环境下确实很牛,但是我的环境还是轻量级点,所以还是基于CentOS来做,就这样研究了两天时间,

spark2.x由浅入深深到底系列六之RDD java api调用scala api的原理

RDD java api其实底层是调用了scala的api来实现的,所以我们有必要对java api是怎么样去调用scala api,我们先自己简单的实现一个scala版本和java版本的RDD和SparkContext 一.简单实现scala版本的RDD和SparkContext class RDD[T](value: Seq[T]) {   //RDD的map操作   def map[U](f: T => U): RDD[U] = {     new RDD(value.map(f))   

heroku create ENOTFOUND: getaddrinfo ENOTFOUND api.heroku.com api.heroku.com:443

$heroku create出现下面的错误: Creating app... !!! ? ENOTFOUND: getaddrinfo ENOTFOUND api.heroku.com api.heroku.com:443 2016/03/17 15:20:05 Error: getaddrinfo ENOTFOUND api.heroku.com api.heroku.com:443 at errnoException (dns.js:26:10) at GetAddrInfoReqWrap.