【问题标题】:Uploading files in a forum with a Web Service in Moodle使用 Moodle 中的 Web 服务在论坛中上传文件
【发布时间】:2016-01-27 15:33:02
【问题描述】:

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

我还发现,在 Moodle 3.0 中,有 2 个与论坛相关的新 WS,它们是 mod_forum_add_discussionmod_forum_add_discussion_post 但我也查看了代码,它们没有允许上传。

然后我决定最好的解决方案是创建一个新的,但我对在 Moodle 中上传文件知之甚少,也找不到太多信息。我对 Moodle 中 WS 的结构有点熟悉,因为我做了 2 个非常简单的 WS,但我不知道该怎么做。

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

提前致谢。

【问题讨论】:

    标签: web-services file-upload moodle


    【解决方案1】:

    您可以查找文件

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

    【讨论】:

    • 非常感谢您的回答,我会尝试您向我提出的建议,看看是否对我有用
    • 我一直在测试您让我调用该服务的内容,我必须进行一些更改才能发送文件。这是文件将与 CURFile 一起发送: $cfile = new CURLFile($file_name_with_full_path);然后 $post = array (...., 'file' => $cfile );和 curl_setopt($ch, CURLOPT_HTTPHEADER,array('Content-Type: multipart/form-data'));我还能够使用自定义 WS 在论坛中创建讨论,然后我会尝试你让我保存文件的内容。谢谢
    • 我试过你的代码来保存文件,它运行良好。谢谢
    • @Joacer 你会分享你创建的网络服务代码吗?谢谢。
    • @arvind 我搜索了他们,我稍后再发布,因为现在我正在工作!
    【解决方案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>";
        }   
    

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-25
      • 1970-01-01
      • 2018-08-02
      • 2022-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多