1. 程式人生 > >Moodle 中文 API 之 文件管理API

Moodle 中文 API 之 文件管理API

reverse string bit /dev/ empty cte extra 回調函數 安全

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