General developer forum

Upload and display file in moodledata folder

 
Picture of Inamullah Khan
Upload and display file in moodledata folder
 

I have created a form for offline training in my plugin. This form contain some fields including a file (certificate) and used moodle data filemanager attribute to upload file. I want to save the the user data in my plugin table and certificate file into moodle directory. The user data is link with th file eupload in mdl_files table. Below is my code to save file in mdl_files table.

$maxbytes = 1000;

$attachmentoptions = array('subdirs'=>false, 'maxfiles'=>99, 'maxbytes'=>$maxbytes);

 if ($fromform = $form->get_data()) {

file_postupdate_standard_filemanager($fromform->attachments, 'attachments', $attachmentoptions, $context, 'mod_resource', 'attachments', $fromform->id);

}

I used this function to save file in moodle data table

$entry = file_postupdate_standard_filemanager($entry, 'attachment', $attachmentoptions, $context, 'mod_glossary', 'attachment', $entry->id); 

The issue is when i save the form data.

This error appears when i am going to save form data.


Error appears on this condition of  file_postupdate_standard_filemanager function.

 if (empty($data->{$field.'_filemanager'})) {

        $data->$field = '';

}

Plus, How can i get uploaded file from mdl_files table ?

Regards,
Inam



 
Average of ratings: -
Davo
Re: Upload and display file in moodledata folder
Core developersParticularly helpful MoodlersPlugin developers

The first parameter to the file_postupdate_standard_filemanager() function should be the $fromform object returned by $form->get_data(). Instead you have given it only one member variable from that object ($fromform->attachments).

Unless you are making changes to the mod_resource plugin, the component param is wrong (it should be something like 'mod_NAMEOFPLUGIN').

The itemid you have specified appears to be the id of the activity (unless I've misunderstood), which is not really useful, as the context already uniquely identifies the area (the itemid should be 0, unless you have multiple file areas in a plugin - e.g. a single forum instance has multiple posts, so each has its own itemid, but a mod_resource instance only has one file area, so it doesn't need the itemid).

To get the uploaded files, you need to get all the files in the file area you specified for files to be saved into:

$fs = get_file_storage();
$files = $fs->get_area_files($context->id, 'mod_NAMEOFPLUGIN', 'attachment', $fromform->id);
foreach ($files as $file) {
   echo $file->get_content();
}


 
Average of ratings: -
Picture of Inamullah Khan
Re: Upload and display file in moodledata folder
 

Thanks for reply. This is how i defined filemanager element in form. 

$mform->addElement('filemanager', 'attachment', 'Attachments', null, array('maxfiles' => 1, 'accepted_types' => '.pdf', 'subdirs' => 0, 'areamaxbytes' => 10485760));


Here is my code to insert data in mdl_files table.

$attachmentoptions = array('subdirs'=>false, 'maxfiles'=>99, 'maxbytes'=>$maxbytes);

 if ($fromform = $form->get_data()) {

file_postupdate_standard_filemanager($fromform->attachment, 'attachment', $attachmentoptions, $context->id, 'block_course_status_tracker', 'attachment', $itemid);

}

Still it throws same error. Error appears in second parameter $field. However i searched in moodle code about this function and everywhere this function calls same way as i defined in my code.

file_postupdate_standard_filemanager($data, $field, array $options, $context, $component, $filearea, $itemid)



     

 
Average of ratings: -
Davo
Re: Upload and display file in moodledata folder
Core developersParticularly helpful MoodlersPlugin developers

Your call to file_postupdate_standard_filemanger() very clearly still starts with the parameter $fromform->attachment.

That is not the same as passing $fromform, as I suggested in my previous post.


 
Average of ratings: -
Picture of Inamullah Khan
Re: Upload and display file in moodledata folder
 

There are two differnet code i used to store file in mdl_files table but both are create 4 entries in database table.

database


1. In this code i used file_save_draft_area_files to save files entries.  

/** course_form.php **/

$attachmentoptions = array('subdirs' => 0, 'areamaxbytes' => 10485760, 'accepted_types' => array('document'));       

$mform->addElement('filemanager', 'attachments', 'Attachments', null, $attachmentoptions );


/** view.php **/

$get_context = get_context_instance(CONTEXT_BLOCK, 84);

$draftitemid = file_get_submitted_draft_itemid('attachments');

echo $draftitemid;

if (empty($entry->id)) {

                $entry = new stdClass;

                $entry->id = 0;

    $form->attachments = $draftitemid;

    $form->set_data($toform);

if ($fromform = $form->get_data()) {

$formdata =  file_save_draft_area_files($fromform->attachments, $get_context->id, 'block_course_status_tracker', 'attachment', $entry->id, $attachmentoptions);

}


2. In this code i used file_postupdate_standard_filemanager  function


/** course_form.php **/

$mform->addElement('filemanager', 'files_filemanager', 'Attachments', null, $attachmentoptions );


/** view.php **/

 if ($fromform = $form->get_data()) {

file_postupdate_standard_filemanager($fromform, 'files', $attachmentoptions, $get_context, 'block_course_status_tracker', 'attachment', $entry->id);

}  

Here is the code to generate $url for the uploaded file

$fs = get_file_storage();

$dir = $fs->get_area_tree($get_context->id, 'block_course_status_tracker', 'attachment', $itemid = false);

foreach ($dir['files'] as $file) {

$url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(), $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename());

echo $url;

}  


This code make this URL and when  i opened this link it show below error

http://localhost/moodle-3.2/pluginfile.php/134/block_course_status_tracker/attachment/0/Negotiation%20Skill_Negotiation%20skills.pdf

file error


One more thing through contenthash in table i checked my moodledata.moodledata

 
Average of ratings: -
Davo
Re: Upload and display file in moodledata folder
Core developersParticularly helpful MoodlersPlugin developers

Have you implemented the function block_course_status_tracker_pluginfile() in blocks/course_status_tracker/lib.php ?

If not, then Moodle has no way of checking that the given user is allowed to view the file, so cannot serve it back.

There are examples throughout the Moodle code, but mod/forum/lib.php, mod_forum_pluginfile() would be a starting point.


 
Average of ratings: -
Picture of Inamullah Khan
Re: Upload and display file in moodledata folder
 

Ok Thanks. I am going to write this function in lib.php but can you please tell me in which file i would call this function? And what will be the $course and $cm value because i am making this offline training page in a block and i don't have any $cm and $course id ? 

function MYPLUGIN_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {

}

 
Average of ratings: -
Davo
Re: Upload and display file in moodledata folder
Core developersParticularly helpful MoodlersPlugin developers

You won't call this function at all.

Moodle will call this function for you, when it receives a request to serve a file with the 'component' set to match your plugin.


 
Average of ratings: -
Picture of Inamullah Khan
Re: Upload and display file in moodledata folder
 

I defined this fucntion in lib.php and now file is downloading but it show error when i open downloaded pdf file. pdf

Here is  block_course_status_tracker_pluginfile function

function block_course_status_tracker_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {

    global $DB;

    if ($context->contextlevel != CONTEXT_BLOCK) {

        return false;

    }

    require_login();

    if ($filearea != 'attachment') {

        return false;

    }

    $itemid = (int)array_shift($args);

    if ($itemid != 0) {

        return false;

    }

    $fs = get_file_storage();

    $filename = array_pop($args);

    if (empty($args)) {

        $filepath = '/';

    } else {

        $filepath = '/'.implode('/', $args).'/';

    }

    $file = $fs->get_file($context->id, 'block_course_status_tracker', $filearea, $itemid, $filepath, $filename);

    if (!$file) {

        return false;

    }

    // finally send the file

    send_stored_file($file, 0, 0, true, $options); // download MUST be forced - security!


 
Average of ratings: -