若依框架(Ruoyi-vue)视频上传与实时预览功能实现详解

张开发
2026/4/18 15:57:19 15 分钟阅读

分享文章

若依框架(Ruoyi-vue)视频上传与实时预览功能实现详解
1. 若依框架视频上传功能概述在内容管理系统开发中视频上传是个常见但容易踩坑的功能点。若依框架Ruoyi-vue作为基于VueSpring Boot的权限管理系统提供了完善的文件上传机制。我最近刚用这个框架完成了一个在线教育平台的项目其中就涉及到视频上传和实时预览功能。说实话第一次实现时遇到了不少问题比如格式校验失效、大文件上传卡顿、回显路径错误等。经过几次迭代优化现在这套方案已经稳定运行半年多。视频上传功能看似简单实则要考虑很多细节前端需要处理格式校验、大小限制、上传进度显示后端要确保文件存储安全、返回正确的访问路径前后端联调时还要注意跨域和权限问题。在若依框架中这些功能都可以通过合理配置Element UI的上传组件和框架自带的后端接口来实现。下面我就从实际项目经验出发手把手带你实现这个功能。2. 前端组件配置与实现2.1 上传组件基础配置首先来看前端部分的实现。若依框架默认集成了Element UI我们可以直接使用它的el-upload组件。这个组件功能强大但配置项较多刚开始用时容易搞混各个回调函数的作用。我在项目中是这样配置的template el-upload classvideo-uploader :actionuploadVideoUrl :on-progressuploadVideoProcess :on-successhandleVideoSuccess :before-uploadbeforeUploadVideo :show-file-listfalse :headersheaders !-- 上传状态判断 -- video v-ifvideoForm.showVideoPath !uploading :srcvideoForm.showVideoPath classuploaded-video controls 您的浏览器不支持视频播放 /video i v-else-if!videoForm.showVideoPath !uploading classel-icon-plus uploader-icon /i el-progress v-ifuploading typecircle :percentageuploadPercent classprogress-bar /el-progress /el-upload /template几个关键配置项说明action设置后端接口地址建议通过环境变量配置before-upload上传前的校验函数这里可以做文件格式和大小检查on-progress上传进度回调用于显示进度条on-success上传成功后的处理函数headers需要携带的认证信息若依框架使用JWT认证2.2 上传逻辑实现接下来是JavaScript部分的实现。这里有几个容易踩坑的地方比如进度条显示逻辑、成功后的回显处理等。我优化后的代码如下script import { getToken } from /utils/auth; export default { data() { return { uploadVideoUrl: process.env.VUE_APP_BASE_API /common/upload, headers: { Authorization: Bearer getToken() }, uploading: false, // 上传状态标志 uploadPercent: 0, // 上传进度 videoForm: { showVideoPath: // 视频回显路径 }, allowedTypes: [ video/mp4, video/ogg, video/webm, video/quicktime // 兼容苹果设备的mov格式 ] }; }, methods: { // 上传前校验 beforeUploadVideo(file) { const isLt50M file.size / 1024 / 1024 50; if (!this.allowedTypes.includes(file.type)) { this.$message.error(仅支持MP4/OGG/WEBM/MOV格式视频); return false; } if (!isLt50M) { this.$message.error(视频大小不能超过50MB); return false; } this.uploading true; return true; }, // 上传进度处理 uploadVideoProcess(event, file, fileList) { this.uploadPercent Math.floor(file.percentage); }, // 上传成功处理 handleVideoSuccess(res, file) { if (res.code 200) { this.videoForm.showVideoPath res.url; this.$message.success(视频上传成功); } else { this.$message.error(res.msg || 上传失败); } this.uploading false; this.uploadPercent 0; } } }; /script这里有几个优化点视频格式校验改用includes方法更简洁添加了苹果设备常用的quicktime类型支持上传状态管理更精细避免异常情况下的UI错乱增加了后端返回结果的错误处理2.3 样式优化最后是样式部分。Element UI默认的上传样式可能不符合项目需求我们可以通过scoped样式进行定制style scoped .video-uploader { display: block; width: 360px; margin: 0 auto; } .uploader-icon { font-size: 28px; color: #8c939d; width: 360px; height: 200px; line-height: 200px; text-align: center; border: 1px dashed #d9d9d9; border-radius: 6px; transition: all 0.3s; } .uploader-icon:hover { border-color: #409eff; } .uploaded-video { width: 360px; height: 200px; display: block; border-radius: 6px; object-fit: contain; background: #000; } .progress-bar { margin: 80px auto; } /style样式优化的重点是统一视频显示区域和上传区域的大小添加鼠标悬停效果提升用户体验设置视频背景为黑色避免某些视频透明背景导致的显示问题进度条位置居中显示3. 后端接口实现3.1 文件上传接口配置若依框架已经内置了文件上传功能位于CommonController中的upload方法。但默认配置可能需要根据项目需求进行调整。我在项目中是这样优化的RestController RequestMapping(/common) public class CommonController { PostMapping(/upload) public AjaxResult uploadFile( RequestParam(file) MultipartFile file, RequestParam(value type, required false) String type) { try { // 校验文件大小 long maxSize 50 * 1024 * 1024; // 50MB if (file.getSize() maxSize) { return AjaxResult.error(文件大小不能超过50MB); } // 校验文件类型 String[] allowedTypes {video/mp4, video/ogg, video/webm, video/quicktime}; if (!Arrays.asList(allowedTypes).contains(file.getContentType())) { return AjaxResult.error(不支持的文件类型); } // 上传文件 String filePath RuoYiConfig.getUploadPath(); String fileName FileUploadUtils.upload(filePath, file); String url ServletUtils.getRequest().getScheme() :// ServletUtils.getRequest().getServerName() : ServletUtils.getRequest().getServerPort() /profile/upload/ fileName; return AjaxResult.success(上传成功, Map.of(url, url)); } catch (Exception e) { return AjaxResult.error(e.getMessage()); } } }关键优化点添加了前后端一致的文件类型校验限制文件大小与前端保持一致返回完整的可访问URL方便前端直接使用使用统一的AjaxResult返回格式3.2 文件存储配置若依框架的文件上传路径配置在application.yml中# 文件路径配置 ruoyi: profile: # 上传路径 uploadPath: /home/ruoyi/uploadPath # 资源映射路径 resourcePath: /profile/**建议根据实际部署环境修改生产环境应该使用绝对路径考虑使用云存储OSS方案替代本地存储注意目录权限设置确保应用有写入权限3.3 跨域与权限处理若依框架已经配置了跨域支持但如果需要调整可以在WebMvcConfig中修改Configuration public class WebMvcConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(*) .allowedMethods(GET, POST, PUT, DELETE) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }对于权限控制框架默认使用PreAuthorize注解可以在Controller方法上添加PreAuthorize(ss.hasPermi(system:video:upload)) PostMapping(/upload) public AjaxResult uploadFile(...) { // ... }4. 常见问题与解决方案4.1 大文件上传优化当视频文件较大时可能会遇到上传超时或内存不足的问题。解决方案包括调整Spring Boot的文件大小限制spring: servlet: multipart: max-file-size: 50MB max-request-size: 50MB分片上传实现方案// 前端分片处理 const chunkSize 5 * 1024 * 1024; // 5MB const chunks Math.ceil(file.size / chunkSize); for (let i 0; i chunks; i) { const chunk file.slice(i * chunkSize, (i 1) * chunkSize); // 上传每个分片... }后端合并分片// 根据分片序号合并文件 File tempFile new File(tempDir, fileName); try (FileOutputStream fos new FileOutputStream(tempFile, true)) { FileUtils.copy(file.getInputStream(), fos); }4.2 视频格式兼容性问题不同浏览器支持的视频格式可能不同。解决方案前端检测浏览器支持格式const video document.createElement(video); const canPlayMP4 video.canPlayType(video/mp4) ! ;后端转码处理// 使用FFmpeg进行格式转换 ProcessBuilder pb new ProcessBuilder( ffmpeg, -i, inputPath, -c:v, libx264, outputPath );4.3 视频封面生成很多场景需要自动生成视频封面可以使用以下方案前端Canvas截取第一帧const video document.createElement(video); video.addEventListener(loadeddata, () { const canvas document.createElement(canvas); canvas.width video.videoWidth; canvas.height video.videoHeight; canvas.getContext(2d).drawImage(video, 0, 0); const thumbnail canvas.toDataURL(image/jpeg); });后端使用FFmpeg生成ProcessBuilder pb new ProcessBuilder( ffmpeg, -i, videoPath, -ss, 00:00:01, -vframes, 1, thumbnailPath );5. 性能优化与安全建议5.1 上传性能优化启用Gzip压缩server: compression: enabled: true mime-types: application/json,application/xml,text/html,text/xml,text/plain,multipart/form-data使用CDN加速静态资源访问实现断点续传功能5.2 安全防护措施文件重命名防止注入String fileName UUID.randomUUID() . FileTypeUtils.getExtension(file);文件内容校验// 检查文件魔数 byte[] bytes file.getBytes(); if (!Arrays.equals(Arrays.copyOf(bytes, 4), new byte[]{0x00, 0x00, 0x00, 0x20})) { throw new RuntimeException(非法文件); }设置文件访问权限Path path Paths.get(filePath); Files.setPosixFilePermissions(path, PosixFilePermissions.fromString(rw-r-----));5.3 监控与日志添加上传日志记录Async public void recordUploadLog(String fileName, long size, String ip) { // 记录到数据库 }监控上传异常ExceptionHandler(MaxUploadSizeExceededException.class) public AjaxResult handleUploadException() { return AjaxResult.error(文件大小超过限制); }在实际项目中视频上传功能往往需要根据具体业务需求进行定制化开发。比如教育平台可能需要添加水印社交应用可能需要压缩视频等。建议在基础功能实现后再逐步添加这些高级特性。

更多文章