Spring MVC整合Thymeleaf运行时上传视频无法播放问题
问题根因
和文件夹锁定无关,本质是两类资源的请求逻辑差异+静态资源配置缺陷共同导致:
- 图片加载是普通全量GET请求,浏览器拿到完整文件就能直接渲染;但video标签播放视频时,默认会发起带
Range头的分片请求,要求服务器返回206状态码的分段数据,支持边下边播、进度条拖动,对资源可用性的校验逻辑更严格。 - 你当前把上传目录指向
src/main/resources/static/是典型的错误实践:这个路径是源码目录,仅在IDE开发环境下可访问,项目打包成jar后该目录不存在且无写入权限;同时Spring默认静态资源处理器对file协议指向的目录,会在启动时扫描文件元数据建立索引,运行中新写入的文件不会被实时加入索引,处理视频分片请求时会判定资源无效,返回不符合浏览器要求的响应,导致播放失败。重启时IDE会重新把src目录的文件同步到编译输出目录、重建资源索引,所以重启后视频能正常播放。 - 代码里拼接的
../videos/相对路径写法不规范,容易出现上下文路径解析错误。
解决方案
第一步:调整上传目录,脱离源码路径
在项目运行工作目录下单独创建专用的上传存储目录(和src平级即可,比如data/upload/videos、data/upload/images),不要把用户上传的动态文件存在源码resources目录下,避免打包、版本提交、重启时文件丢失。
// 视频上传根目录,可通过配置文件灵活注入,示例为项目根目录下的相对路径 private static final String VID_UPLOAD_DIR = "data/upload/videos/"; // 服务启动时自动创建目录,避免路径不存在报错 @PostConstruct public void initUploadDir() { File videoDir = new File(VID_UPLOAD_DIR); if (!videoDir.exists()) { videoDir.mkdirs(); } }
修正上传方法里的路径存储逻辑,不要用../跨级相对路径,只存文件名即可:
// 删除原有 String part="../videos/"+fileName; 逻辑 member.setVideo(fileName);
第二步:修正静态资源配置,开启分片支持和实时资源检测
修改application配置,把独立上传目录加入静态资源映射,开发环境关闭静态资源缓存,保证新上传文件实时生效:
# 静态资源路径优先级:外部上传目录 > 项目内置static目录 spring.web.resources.static-locations[0]=file:data/upload/videos/ spring.web.resources.static-locations[1]=file:data/upload/images/ spring.web.resources.static-locations[2]=classpath:/static/ # 开发环境关闭静态资源缓存,实时识别新上传文件 spring.web.resources.cache.period=0 spring.web.resources.chain.cache=false # 开启资源元数据实时检测,自动支持Range分片请求(视频播放必需) spring.web.resources.chain.strategy.content.enabled=true
如果用Java配置类管理静态资源映射,显式注册资源处理器即可:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/videos/**") .addResourceLocations("file:data/upload/videos/") .setCachePeriod(0) .resourceChain(true) .addResolver(new PathResourceResolver()); } }
第三步:修正前端视频引用路径
Thymeleaf里用绝对上下文路径引用视频,避免相对路径解析错误:
<video controls width="720" height="405"> <source th:src="@{/videos/{filename}(filename=${video.path})}" type="video/mp4"> 您的浏览器不支持视频播放标签 </video>
生产环境优化提示
- 生产环境不需要把缓存周期设为0,可设置合理的浏览器缓存时间,上传视频时给文件名拼接UUID随机前缀,避免同名文件缓存导致新视频不生效。
- 生产环境建议把上传目录配置到服务器独立的数据盘路径,不要和应用部署包放在一起,方便应用升级时迁移文件。
内容的提问来源于stack exchange,提问作者Lekan Swansons
相关产品推荐
相关产品推荐

