使用Moodle中的Web服务在论坛中上传文件

时间:2016-01-27 15:33:02

标签: web-services file-upload moodle

我需要通过 Web服务将文件上传到moodle的论坛,我一直在搜索,我发现存在一个名为core_files_upload()的WS。我查看了这个WS的代码,这个WS的上下文级别只是( block,course,coursecat,system,user或module ),上下文论坛不存在,这个WS是{{1 }}。

我还发现在Moodle 3.0中有两个与论坛相关的新WS,它们是 mod_forum_add_discussion mod_forum_add_discussion_post 但是我也查看了代码并且他们没有&#39 ; t允许上传。

然后我决定最好的解决方案是创建一个新的解决方案,但我不太了解在 Moodle 中上传文件并且找不到更多信息。我对Moodle中WS的结构有点熟悉,因为我已经制作了2个非常简单的WS,但我不知道如何做到这一点。

如果有人知道该怎么做或有任何可能有用的示例或文档,那将会有所帮助。

提前致谢。

2 个答案:

答案 0 :(得分:2)

您可以查找文件

/webservice/upload.php

    this file is for uploading files

$params = array('token'=>$token, 'filepath' => $filepath
                , 'filearea'=>'draft') + $_FILES ;
    $serverurl = <domainname>. '/webservice/upload.php'. '?token=' . $token;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_VERBOSE, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");
    curl_setopt($ch, CURLOPT_URL, $serverurl);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
    $response = curl_exec($ch);  

或者这个代码可以帮助你,它将在moodle数据中创建一个文件并从临时文件中记录在文件表中。

$fs = get_file_storage();

$target_path = <target-path>;
$context = get_context_instance(CONTEXT_USER, $userID, MUST_EXIST);
$cm         = get_coursemodule_from_instance('forum', $forum->id);
    $modcontext = context_module::instance($cm->id, MUST_EXIST);

//saving in draft
$item = rand();
$file_record = array('contextid'=>$context->id, 'component'=>'user', 'filearea'=>'draft', 'itemid'=>$item,
'filepath'=>"/", 'filename'=><filename>, 'userid'=>$userID);
$fs->create_file_from_pathname($file_record, $CFG->dirroot."/".$target_path.<filename>);

// saving for post
$file_record = array('contextid'=>$modcontext->id, 'component'=>'mod_forum', 'filearea'=>'post', 'itemid'=>$post->id,
'filepath'=>"/", 'filename'=><filename>, 'userid'=>$userID);
$fs->create_file_from_pathname($file_record, $CFG->dirroot."/".$target_path.$imagefileEnc);

答案 1 :(得分:2)

应@insightful的要求,我将发布我的代码,我希望这有助于某人

首先是WS的externallib.php

<强> externallib.php

require_once($CFG->libdir . "/externallib.php");
require_once($CFG->libdir . "/filelib.php");

class local_upload_tfg_external extends external_api {

    /**
     * Returns description of method parameters
     * @return external_function_parameters
     */
    public static function upload_tfg_parameters() {
        return new external_function_parameters(
                array('community_key' => new external_value(PARAM_TEXT, 'Comunidad a la que se subira el TFG o TFM.', VALUE_REQUIRED, '', NULL_NOT_ALLOWED),
                    'username' => new external_value(PARAM_TEXT, 'Usuario que sube el archivo.', VALUE_REQUIRED, '', NULL_NOT_ALLOWED),
                    'folder_name' => new external_value(PARAM_TEXT, 'Directorio donde se subira el archivo.', VALUE_REQUIRED, '', NULL_NOT_ALLOWED))
        );
    }

    public static function upload_tfg($community_key, $username, $folder_name) {    
        global $CFG, $DB, $USER;
        require_once($CFG->dirroot . "/mod/forum/lib.php");

         $params = self::validate_parameters(self::upload_tfg_parameters(),
                                            array(
                                                'community_key' => $community_key,
                                                'username' => $username,
                                                'folder_name' => $folder_name
                                            ));

        //Context validation
        //OPTIONAL but in most web service it should present
        $contextoUser = get_context_instance(CONTEXT_USER, $USER->id);
        self::validate_context($contextoUser);

        $fs = get_file_storage();

        $warnings = array();    

        //We get the course to which the file must be uploaded
        $sql = "SELECT id FROM mdl_course WHERE idnumber = ?";      
        $result = $DB->get_records_sql($sql, array($community_key));

        foreach ( $result as $n ) {     
            $courseid = $n->id;
        }   

        if( is_null($courseid)){
            throw new moodle_exception('no_course','No existe el curso');
        }

        //e get the forum to upload the file
        $sql = "SELECT f.id FROM mdl_forum f , mdl_course c WHERE c.idnumber = ? AND c.id = f.course AND f.name = ?";
        $result = $DB->get_records_sql($sql, array($community_key, $folder_name));

        foreach ( $result as $n ) {     
            $forumid = $n->id;
        }   

        if( is_null($forumid)){
            throw new moodle_exception('no_forum','No existe el foro');
        }

        //We get the user who wants to upload the file
        $sql = "SELECT id FROM mdl_user WHERE username = ?";
        $result = $DB->get_records_sql($sql, array($username));

        foreach ( $result as $n ) { 

            $userid = $n->id;
        }   

        if( is_null($userid)){
            throw new moodle_exception('no_user','No existe el usuario');
        }

        //We check if the user belongs to the course
        $contextCourse = context_course::instance($courseid); 
        $enrolled = is_enrolled($contextCourse, $userid, '', true);

        if( !$enrolled){
            throw new moodle_exception('user_no_enrolled','El usuario no está en el curso');
        }

        //Files received    
        $numFiles = count($_FILES);         

        if($numFiles > 0){  
            // Request and permission validation.
            $forum = $DB->get_record('forum', array('id' => $forumid), '*', MUST_EXIST);
            list($course, $cm) = get_course_and_cm_from_instance($forum, 'forum');

            $context = context_module::instance($cm->id);
            self::validate_context($context);

            // Normalize group.
            if (!groups_get_activity_groupmode($cm)) {
                // Groups not supported, force to -1.
                $groupid = -1;
            } else {
                // Check if we receive the default or and empty value for groupid,
                // in this case, get the group for the user in the activity.
                if ($groupid === -1 ) {
                    $groupid = groups_get_activity_group($cm);
                } else{
                     $groupid = -1;
                }
            }

            if (!forum_user_can_post_discussion($forum, $groupid, -1, $cm, $context)) {
                throw new moodle_exception('cannotcreatediscussion', 'forum');
            }

            $thresholdwarning = forum_check_throttling($forum, $cm);
            forum_check_blocking_threshold($thresholdwarning);

            foreach ($_FILES as $fieldname=>$uploaded_file) {

                // check upload errors
                if (!empty($_FILES[$fieldname]['error'])) {     

                    switch ($_FILES[$fieldname]['error']) {
                    case UPLOAD_ERR_INI_SIZE:
                        throw new moodle_exception('upload_error_ini_size', 'repository_upload');
                        break;
                    case UPLOAD_ERR_FORM_SIZE:
                        throw new moodle_exception('upload_error_form_size', 'repository_upload');
                        break;
                    case UPLOAD_ERR_PARTIAL:
                        throw new moodle_exception('upload_error_partial', 'repository_upload');
                        break;
                    case UPLOAD_ERR_NO_FILE:
                        throw new moodle_exception('upload_error_no_file', 'repository_upload');
                        break;
                    case UPLOAD_ERR_NO_TMP_DIR:
                        throw new moodle_exception('upload_error_no_tmp_dir', 'repository_upload');
                        break;
                    case UPLOAD_ERR_CANT_WRITE:
                        throw new moodle_exception('upload_error_cant_write', 'repository_upload');
                        break;
                    case UPLOAD_ERR_EXTENSION:
                        throw new moodle_exception('upload_error_extension', 'repository_upload');
                        break;
                    default:
                        throw new moodle_exception('nofile');
                    }
                }               

                /*$file = new stdClass();
                $file->filename = clean_param($_FILES[$fieldname]['name'], PARAM_FILE);
                // check system maxbytes setting
                if (($_FILES[$fieldname]['size'] > get_max_upload_file_size($CFG->maxbytes))) {
                    // oversize file will be ignored, error added to array to notify web service client
                    $file->errortype = 'fileoversized';
                    $file->error = get_string('maxbytes', 'error');
                } else {
                    $file->filepath = $_FILES[$fieldname]['tmp_name'];
                    // calculate total size of upload
                    //$totalsize += $_FILES[$fieldname]['size'];
                }
                $files[] = $file;*/

                $filename = $_FILES[$fieldname]['name'];
                $filepath = $_FILES[$fieldname]['tmp_name'];

                // Create the discussion.
                $discussion = new stdClass();
                $discussion->course = $course->id;
                $discussion->forum = $forum->id;
                $discussion->message = "<p>".$filename."</p>";
                $discussion->messageformat = FORMAT_HTML;   // Force formatting for now.
                $discussion->messagetrust = trusttext_trusted($context);
                $discussion->itemid = 0;
                $discussion->groupid = $groupid;
                $discussion->mailnow = 0;
                $discussion->subject = $filename;
                $discussion->name = $discussion->subject;
                $discussion->timestart = 0;
                $discussion->timeend = 0;

                if ($discussionid = forum_add_discussion($discussion)) {
                    $discussion->id = $discussionid;

                    //We update the user of the discursion to the one of the user received
                    $sql = "UPDATE mdl_forum_discussions SET userid= ? WHERE id = ?";
                    $DB->execute($sql, array($userid, $discussionid));                  
/*
                    // Trigger events and completion.
                    $params = array(
                        'context' => $context,
                        'objectid' => $discussion->id,
                        'other' => array(
                            'forumid' => $forum->id,
                        )
                    );
                    $event = \mod_forum\event\discussion_created::create($params);
                    $event->add_record_snapshot('forum_discussions', $discussion);
                    $event->trigger();

                    $completion = new completion_info($course);
                    if ($completion->is_enabled($cm) && ($forum->completiondiscussions || $forum->completionposts)) {
                        $completion->update_state($cm, COMPLETION_COMPLETE);
                    }

                    $settings = new stdClass();
                    $settings->discussionsubscribe = false; //discussionsubscribe (bool); subscribe to the discussion?, default to true
                    forum_post_subscription($settings, $forum, $discussion          

                    //se guardara el fichero    

                    // Get any existing file size limits.
                    //$maxareabytes = FILE_AREA_MAX_BYTES_UNLIMITED;
                    //$maxupload = get_user_max_upload_file_size($context, $CFG->maxbytes);

                    // Check the size of this upload.
                    //if ($maxupload !== USER_CAN_IGNORE_FILE_SIZE_LIMITS && $totalsize > $maxupload) {
                    //  throw new file_exception('userquotalimit');
                    //}
                    */

                    //We get the course to which the file must be uploaded
                    $sql = "SELECT id FROM mdl_forum_posts WHERE discussion = ? ORDER BY id ASC LIMIT 1";
                    $result = $DB->get_records_sql($sql, array($discussionid));

                    foreach ( $result as $n ) { 
                        $postid = $n->id;
                    }   

                    if( is_null($postid)){
                        throw new moodle_exception('no_post','No existe el post');
                    }

                    //We update the post to put the user that they send us and indicate that they have a file
                    $sql = "UPDATE mdl_forum_posts SET userid= ?, attachment= 1 WHERE id = ?";
                    $DB->execute($sql, array($userid, $postid));

                    $user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);

                    $file_record = new stdClass;
                    $file_record->component = 'mod_forum';
                    $file_record->contextid = $context->id; 
                    $file_record->userid    = $userid; 
                    $file_record->filearea  = 'attachment';
                    $file_record->filename = $filename;
                    $file_record->filepath  = '/';
                    $file_record->itemid    = $postid; 
                    $file_record->license   = $CFG->sitedefaultlicense;
                    $file_record->author    = fullname($user);
                    $file_record->source    = $filename;

                    //Check if the file already exist
                    $existingfile = $fs->file_exists($file_record->contextid, $file_record->component, $file_record->filearea,
                                $file_record->itemid, $file_record->filepath, $file_record->filename);
                    if ($existingfile) {
                        throw new file_exception('filenameexist');
                    } else {
                        $stored_file = $fs->create_file_from_pathname($file_record, $filepath);
                    }
                } else {
                    throw new moodle_exception('couldnotadd', 'forum');
                }   
            }           
        }else{
            throw new moodle_exception('nofile');
        }

        $result = array();
        $result['discussionid'] = $discussionid;
        $result['warnings'] = $warnings;
        return $result;
    }   

    /**
     * Returns description of method result value
     * @return external_multiple_structure
     */
    public static function upload_tfg_returns() {
        return new external_single_structure(
            array(
                'discussionid' => new external_value(PARAM_INT, 'New Discussion ID'),
                'warnings' => new external_warnings()
            )
        );
    }

}

示例来调用此WS可能是这样的:

    $target_url = "http://localhost/pruebaMoodle/webservice/rest/server.php";   
    //$target_url = "http://localhost/upload.php";  

    $username      = "raula";                                   //User uploading the file (must belong to the course)
    $community_key = "c15c033a43976gPT";                        //custom identifier of course
    $folder_name   = "Course 2016";                             //Name of the forum to which the file will be uploaded
    $fname         = 'Prueba.txt';                              //Name of the file or path where it is located but is in the same directory as this file
    $token         = "28b054f102a75a0eab2a0053fd930d62";        //token created for ws

    $file_name_with_full_path = realpath($fname);   
    $cfile = new CURLFile($file_name_with_full_path);

    $post = array (
              'username'     => $username,
              'community_key' => $community_key,
              'folder_name'   => $folder_name,          
              'wstoken'   => $token,    
              'wsfunction'   => 'upload_tfg_tfm',   
              'moodlewsrestformat'   => 'json',
              'upload_file' => $cfile
              );    

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $target_url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");   
    curl_setopt($ch, CURLOPT_HTTPHEADER,array('User-Agent: Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15','Referer: http://localhost','Content-Type: multipart/form-data'));
    curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);   
    curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);  
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);


    $result = curl_exec ($ch);

    if ($result === FALSE) {
        echo "Error sending " . $fname .  " " . curl_error($ch) . "\n";
        curl_close ($ch);
    }else{
        curl_close ($ch);
        echo  "<br><br>Result: " . $result. "<br>";
    }   

我希望这可以为你服务