如何在Moodle中存储图片?自定义驾照上传模块开发求助
问题分析与解决方案
你的代码当前核心问题有两个:
- 前端点击拍照后直接触发本地下载,未将图片数据传递到Moodle后端
- 后端尝试使用
create_file_from_url存储图片,但imgURL是前端JS变量,后端无法获取,且该方法仅适用于从外部URL拉取文件,不处理前端传来的base64格式图片
以下是修改后的完整方案:
1. 前端代码修改(替换原有JS和HTML)
移除下载按钮,通过AJAX将图片base64数据发送到后端:
修改后的HTML部分
echo '<body> <div id="container"> <video autoplay="true" id="video"></video> <button id="btn">拍摄照片</button> <canvas id="canvas" class="hidden"></canvas> </div> </body>';
修改后的JS部分
const video = document.querySelector('#video') const btn = document.querySelector('#btn') const canvas = document.querySelector('#canvas') if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) { navigator.mediaDevices.getUserMedia({video: true}) .then(stream => { video.srcObject = stream }) .catch(error => { console.log('访问摄像头出错') }) } btn.addEventListener('click', () =>{ const width = video.videoWidth, height = video.videoHeight const context = canvas.getContext('2d') canvas.width = width canvas.height = height context.drawImage(video, 0, 0, width, height) // 移除base64前缀,只保留原始编码数据 const imgData = canvas.toDataURL('image/png').replace('data:image/png;base64,', '') // 发送AJAX请求到后端 fetch(window.location.href, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' }, body: `action=uploadphoto&imgdata=${encodeURIComponent(imgData)}&id=<?php echo $id; ?>&sesskey=<?php echo sesskey(); ?>` }) .then(response => response.json()) .then(data => { if (data.success) { alert('照片上传成功!') btn.disabled = true // 可选:上传后禁用按钮 } else { alert('上传失败:' + data.error) } }) .catch(error => { console.error('上传出错:', error) alert('上传出错,请重试') }) })
2. 后端代码修改(view.php)
在require_capability之后添加上传处理逻辑,并删除原有无效的存储代码:
添加上传处理逻辑
// 处理照片上传请求 if (optional_param('action', '', PARAM_ALPHA) === 'uploadphoto' && confirm_sesskey()) { // 验证用户提交权限 require_capability('mod/driverslicense:submit', $context); $imgdata = required_param('imgdata', PARAM_TEXT); // 解码base64数据 $imgdata = base64_decode($imgdata); if ($imgdata === false) { echo json_encode(['success' => false, 'error' => '无效的图片数据']); die(); } $fs = get_file_storage(); // 构建文件存储信息:用用户ID作为itemid,确保每个用户照片独立存储 $fileinfo = array( 'contextid' => $context->id, 'component' => 'mod_driverslicense', 'filearea' => 'student_photos', // 自定义清晰的文件存储区域名 'itemid' => $USER->id, 'filepath' => '/', 'filename' => 'drivers_license_' . $USER->id . '.png' ); // 删除用户已存在的旧照片(可选) $existing_file = $fs->get_file( $fileinfo['contextid'], $fileinfo['component'], $fileinfo['filearea'], $fileinfo['itemid'], $fileinfo['filepath'], $fileinfo['filename'] ); if ($existing_file) { $existing_file->delete(); } // 存储图片文件 $file = $fs->create_file_from_string($fileinfo, $imgdata); if ($file) { echo json_encode(['success' => true]); } else { echo json_encode(['success' => false, 'error' => '图片存储失败']); } die(); }
删除原有无效代码
移除以下这段无法运行的代码:
$fs = get_file_storage(); // Prepare file record object $fileinfo = array( 'contextid' => $context->id, // ID of context 'component' => 'mod_driverslicense', // usually = table name 'filearea' => 'driverslicense', // usually = table name 'itemid' => 0, // usually = ID of row in table 'filepath' => '/', // any path beginning and ending in / 'filename' => 'driverslicensefront.png'); // any filename $fs->create_file_from_url($fileinfo, imgURL );
3. 额外配置(权限)
确保在模块的db/access.php中添加提交权限:
$capabilities = array( // ... 其他已有权限 'mod/driverslicense:submit' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => array( 'student' => CAP_ALLOW ) ), );
内容的提问来源于stack exchange,提问作者Krupp J
相关产品推荐
相关产品推荐

