1.导入依赖:
<!-- 文件上传 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- 阿里巴巴JSON处理器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<!-- 视频获取第一帧 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>0.8</version>
</dependency>
<!--druid数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
第二步:创建uploadFileController
package com.rain.controller;
import com.rain.pojo.CourseTable;
import com.rain.service.CourseService;
import com.rain.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Map;
@RestController
public class UploadController {
@Autowired
private FileService uploadService;
@Autowired
CourseService courseService;
/**
* 视频文件上传
* @param request
* @return
* @throws Exception
*/
@RequestMapping(value ="/uploadVideo",method=RequestMethod.POST)
public Map<String, Object> uploadVideo(MultipartFile file, HttpServletRequest request, CourseTable table) throws Exception{
Map<String,Object> map= uploadService.uploadVideo(file, request);
String name= (String) map.get("FileURL");
table.setCoursePic(name);
courseService.insertCourse(table);
return map;
}
/**
* 图片文件上传
* @param request
* @return
* @throws Exception
*/
@RequestMapping(value ="/uploadImage",method= RequestMethod.POST)
public Map<String, Object> uploadImage(MultipartFile file, HttpServletRequest request) throws Exception{
return uploadService.uploadImage(file, request);
}
}
第三步:前端代码
<form action="/uploadVideo" method="post" enctype="multipart/form-data">
<div class="col-md-12">
<div class="mb-3">
<label class="form-label">名称:</label>
<input class="form-control" type="text" placeholder="课程名字" name="courseName">
</div>
</div>
<div class="col-md-12">
<div class="mb-3">
<label class="form-label">文件:</label>
<input class="form-control" type="file" name="file">
</div>
</div>
<div class="col-md-12">
<div class="mb-3">
<input th:text="${tea.teacherName}" class="form-control" type="hidden" name="courseInstructor">
</div>
</div>
<div class="form-group mb-0">
<button class="btn btn-danger" type="button">重置</button>
<!-- <button class="btn btn-primary" type="button">重置</button>-->
<input class="btn btn-primary" type="submit" value="确认上传">
<!-- <input class="btn btn-danger" type="submit" value="确认上传">-->
</div>
</form>
第四步:创建文件上传 service 层 和接口实现 lmpl 类
Service层
package com.rain.service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
public interface FileService {
/**
* 视频文件上传
* @param request
* @return
*/
public Map<String, Object> uploadVideo(MultipartFile file, HttpServletRequest request) throws Exception;
/**
* 图片文件上传
* @param request
* @return
*/
public Map<String, Object> uploadImage(MultipartFile file,HttpServletRequest request) throws Exception;
}
lmpl层:
package com.rain.service;
import com.rain.SysUtils.Utils;
import org.apache.log4j.spi.ErrorCode;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Transactional
@Service("UploadService")
public class FileServicelmpl implements FileService {
@Override
public Map<String, Object> uploadVideo(MultipartFile file, HttpServletRequest request) throws Exception {
Map<String, Object> resultMap=new HashMap<String, Object>();
// String basePath = request.getScheme() + "://" + request.getServerName()
// + ":" + request.getServerPort()+"/mimi/upload/video/";
Long time = new Date().getTime();
String fileName = file.getOriginalFilename();//文件原始名称
String suffixName = fileName.substring(fileName.lastIndexOf("."));//从最后一个.开始截取。截取fileName的后缀名
String newFileName = time+suffixName; //文件新名称
//设置文件存储路径,可以存放在你想要指定的路径里面
String rootPath="D:/videos/"+File.separator+"upload/video/"; //上传视频存放位置
//以下是视频保存的路径为了网页内展示,之后必须得改
String filePath = rootPath+newFileName;
File newFile = new File(filePath);
//判断目标文件所在目录是否存在
if(!newFile.getParentFile().exists()){
//如果目标文件所在的目录不存在,则创建父目录
newFile.getParentFile().mkdirs();
}
//将内存中的数据写入磁盘
file.transferTo(newFile);
//视频上传保存url
String videoUrl = rootPath + newFileName;
//视频封面图处理
String newImgName = time+".jpg";
String framefile = rootPath + newImgName;
String imgUrlSave = rootPath+newImgName;//图片最终位置路径
//视频截取封面图
String imgUrl= Utils.getVedioImg(videoUrl, framefile, imgUrlSave);
resultMap.put("videoUrl", videoUrl);
resultMap.put("imgUrl", imgUrl);
// resultMap.put(ErrorCode.STATE, ErrorCode.SUCCESS);
resultMap.put("FileName",imgUrlSave);
System.out.println("上传的文件名为:"+fileName+",后缀名为:"+newFileName);
return resultMap;
}
@Override
public Map<String, Object> uploadImage(MultipartFile file, HttpServletRequest request) throws Exception {
Map<String, Object> resultMap=new HashMap<String, Object>();
String basePath = request.getScheme() + "://" + request.getServerName()
+ ":" + request.getServerPort()+"/image/upload/images/";
Long time = new Date().getTime();
String fileName = file.getOriginalFilename();//文件原始名称
String suffixName = fileName.substring(fileName.lastIndexOf("."));//从最后一个.开始截取。截取fileName的后缀名
String newFileName = time+suffixName; //文件新名称
//设置文件存储路径,可以存放在你想要指定的路径里面
String rootPath="D:/image/"+File.separator+"upload/images/"; //上传图片存放位置
String filePath = rootPath+newFileName;
File newFile = new File(filePath);
//判断目标文件所在目录是否存在
if(!newFile.getParentFile().exists()){
//如果目标文件所在的目录不存在,则创建父目录
newFile.getParentFile().mkdirs();
}
//将内存中的数据写入磁盘
file.transferTo(newFile);
//图片上传保存url
String imgUrl = basePath + newFileName;
resultMap.put("imgUrl", imgUrl);
return resultMap;
}
}
第五步:yml文件配置
spring:
# 发送邮件 yml
mail:
host: smtp.163.com
# 发送者账号
username: qxl03590525@163.com
# 授权密码,非登录密码,这里的授权密码是第三方授权的密匙
password: JQABULBEVZKRWWQC
default-encoding: UTF-8
# 数据库连接驱动,4大金刚
datasource:
url: jdbc:mysql://127.0.0.1:3306/rainclass?characterEncoding=UTF-8
username: root
password: root123
driver-class-name: com.mysql.cj.jdbc.Driver
#mapper xml 文件扫描
mybatis:
typeAliasesPackage: com.rain.pojo
mapperLocations: classpath:mapper/*.xml
# 分页依赖
hepagehelper:
lperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
# mvc 视图解析器
mvc:
view:
prefix: /templates/*
suffix: .
static-location: assets/**
# web 网页静态资源加载路径
web:
resources:
static-locations: file:d:/images,classpath:/META-INF/resources/,classpath:/resources/,classpath:static/,classpath:/public/
#文件上传配置
servlet:
multipart:
max-file-size: 500MB
max-request-size: 500MB
enabled: true
# thymeleaf:
# cache: false
#服务开启的端口
server:
port: 8080
# 打印日志列表
logging:
path=D:/data/mylog.txt
#对应servlet 的session 过期时间
servlet:
session:
timeout: 3600s
第六步:上传文件工具包
package com.rain.SysUtils;
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.springframework.context.annotation.Configuration;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Configuration
public class Utils {
public static boolean isEmpty(Object item) {
boolean flag=true;
if(item!=null) {
flag=false;
}
if(item instanceof String) {
String item2=(String) item;
if(item2.length()!=0) {
flag=false;
}else {
flag=true;
}
}
return flag;
}
public static String SimpleDate(Date date) {
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm");
String result=simpleDateFormat.format(date);
return result;
}
public static Date Parse(String dateString) throws ParseException {
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date date=simpleDateFormat.parse(dateString);
return date;
}
/**
* 获取视频图片
* @param videofile 源视频文件路径
* @param framefile 截取帧的图片存放路径
* @param imgfile 视频封面图保存路径
* @return
*/
public static String getVedioImg(String videofile, String framefile,String imgfile){
String ImgUrl="";
//截取封面图
try {
fetchFrame(videofile, framefile);
} catch (Exception e) {
e.printStackTrace();
}
// 完整的ImgUrl
ImgUrl = imgfile;//视频封面图保存路径
return ImgUrl;
}
/**
* 获取指定视频的帧并保存为图片至指定目录
* @param videofile 源视频文件路径
* @param framefile 截取帧的图片存放路径 例:F:\hfkjrecorder\target\4.jpg
* @throws Exception
*/
public static void fetchFrame(String videofile, String framefile) throws Exception {
//long start = System.currentTimeMillis();
File targetFile = new File(framefile);
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile);
ff.start();
int lenght = ff.getLengthInFrames();
int i = 0;
int interceptionFrames = 30;//截取第几帧
//默认截取第50帧,如果第50帧大于视频总帧数的8成直接取长度lenght * 0.3
if(interceptionFrames >= lenght * 0.8) {
interceptionFrames = (int)(lenght * 0.3);
}
Frame f = null;
while (i < lenght) {
// 过滤 前 interceptionFrames 帧,避免出现全黑的图片,依自己情况而定
f = ff.grabFrame();
if ((i > interceptionFrames) && (f.image != null)) {
break;
}
i++;
}
opencv_core.IplImage img = f.image;
int owidth = img.width();
int oheight = img.height();
// 对截取的帧进行等比例缩放 宽350、高160
// if(owidth > oheight) {//宽大于高
//
// }else {//高大于宽
//
// }
int width = 800;
int height = (int) (((double) width / owidth) * oheight);
/**
width - 所创建图像的宽度
height - 所创建图像的高度
imageType - 所创建图像的类型
TYPE_3BYTE_BGR - 表示一个具有 8 位 RGB 颜色分量的图像,对应于 Windows 风格的 BGR 颜色模型,具有用 3 字节存储的 Blue、Green 和 Red 三种颜色。
*/
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
//此方法返回 Graphics2D,但此处是出于向后兼容性的考虑。
bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH),
0, 0, null);
ImageIO.write(bi, "jpg", targetFile);
//ff.flush();
ff.stop();
// System.out.println(System.currentTimeMillis() - start);
}
}