采用SSM框架技术,其中涉及模块,根据网上一些博客因个人项目而整理开发,可作为他人开发参考
本人开发参考:https://zoutao.blog.csdn.net/article/details/81747046

1、处理工具类及配置文件

(1)配置文件serviceconfig.properties

本地目录文件,Linux环境可更换配置

#临时的视频存储路径,转码完成后删除
TEMPORARY_VIDEO_PATH=D:/zhongjianjian/temp/
#转码成功mp4视频存放路径
TRANSCODE_VIDEO_MP4PATH=D:/zhongjianjian/finshvideo/
#转码ffmpeg.exe工具路径
FFMPEG_PATH=D:/zhongjianjian/tools/ffmpeg.exe
#转码mencoder.exe工具路径
MENCODER_PATH=D:/zhongjianjian/tools/mencoder.exe
#视频截图存放路径
filePath=D:/zhongjianjian/views/static/

(2)加载静态资源服务类

ResourceService.java 方便用于加载配置文件 serviceconfig.properties 中的变量

package com.sslt.utils;import java.util.Enumeration;
import java.util.ResourceBundle;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 加载静态资源服务* @author **/
public class ResourceService {private final static Logger logger = LoggerFactory.getLogger(ResourceService.class);/** 参数配置文件  */public static ResourceBundle rb = null;/*** 项目启动系统所需配置文件,仅此一次*/static{rb = ResourceBundle.getBundle("serviceconfig");}public static void refresh() {logger.info("开始重载serviceconfig配置文件......");ResourceBundle.clearCache();rb = ResourceBundle.getBundle("serviceconfig");logger.info("检查serviceconfig文件是否重载完成......");Enumeration<String> keys = rb.getKeys();while(keys.hasMoreElements()){String key = keys.nextElement();String value = rb.getString(key);logger.info("serviceconfig配制已经重载--> "+key + " : " + value);}logger.info("serviceconfig配制文件重载完成!");}
}

(3)自定义响应类

ResultBean.java 作为统一响应数据格式

package com.sslt.common;/*** 自定义响应结构*/
public class ResultBean {// 响应业务状态private Integer status;// 响应消息private String msg;// 响应中的数据private Object data;public static ResultBean build(Integer status, String msg, Object data) {return new ResultBean(status, msg, data);}public static ResultBean success(Object data) {return new ResultBean(data);}public static ResultBean success() {return new ResultBean(null);}public ResultBean() {}public static ResultBean build(Integer status, String msg) {return new ResultBean(status, msg, null);}public ResultBean(Integer status, String msg, Object data) {this.status = status;this.msg = msg;this.data = data;}public ResultBean(Object data) {this.status = 200;this.msg = "SUCCESS";this.data = data;}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}}

响应码工具类 GlobalState.java,可配置统一静态变量

package com.sslt.common;/*** 静态变量工具类* @author MINI**/
public class GlobalState {public static final Integer RESULTSTATUS = 200;           // 默认返回成功状态码public static final Integer FAILSTATUS = 401;             // 失败状态public static final Integer PASTSTATUS = 400;             // 过期状态}

(4)文件校验类

FileUploadToolUtil.java 检测文件类型包括图片和视频格式,检测文件格式是否支持、大小和不能为空

package com.sslt.utils;import java.io.File;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Iterator;import javax.servlet.http.HttpServletRequest;import org.springframework.web.multipart.MultipartFile;import com.sslt.common.GlobalState;
import com.sslt.common.ResultBean;/*** 文件校验* @author MINI**/
public class FileUploadToolUtil {// 文件最大500Mprivate static long upload_maxsize = 500 * 1024 * 1024;// 文件允许格式private static String[] allowFiles = { ".rar", ".doc", ".docx", ".zip",".pdf", ".txt", ".swf", ".xlsx", ".gif", ".png", ".jpg", ".jpeg",".bmp", ".xls", ".mp4", ".flv", ".ppt", ".avi", ".mpg", ".wmv",".3gp", ".mov", ".asf", ".asx", ".vob", ".wmv9", ".rm", ".rmvb" };public static ResultBean createFile(MultipartFile multipartFile, HttpServletRequest request) {Integer status = GlobalState.RESULTSTATUS;String msg = "";String fileName = multipartFile.getOriginalFilename().toString();// 判断文件不为空if (multipartFile.getSize() != 0 && !multipartFile.isEmpty()) {// 判断文件大小if (multipartFile.getSize() <= upload_maxsize) {// 文件类型判断if (!checkFileType(fileName)) {status = GlobalState.FAILSTATUS;msg = fileName + "文件,系统暂不支持" + fileName.substring(fileName.lastIndexOf("."),fileName.length()) + "的文件格式!";}} else {status = GlobalState.FAILSTATUS;msg = "文件大小超范围";}} else {status = GlobalState.FAILSTATUS;msg = "上传文件不能为空";}return ResultBean.build(status, msg);}/*** 文件类型判断** @param fileName* @return*/public static boolean checkFileType(String fileName) {Iterator<String> type = Arrays.asList(allowFiles).iterator();while (type.hasNext()) {String ext = type.next();if (fileName.toLowerCase().endsWith(ext)) {return true;}}return false;}/*** 获取文件扩展名** @return string*/public static String getFileExt(String fileName) {return fileName.substring(fileName.lastIndexOf("."));}/*** 依据原始文件名生成新文件名* @return*/public static String getName(String fileName) {Iterator<String> type = Arrays.asList(allowFiles).iterator();while (type.hasNext()) {String ext = type.next();if (fileName.contains(ext)) {String newFileName = fileName.substring(0, fileName.lastIndexOf(ext));return newFileName;}}return "";}/*** 文件大小,返回kb.mb** @return*/public static String getSize(File file) {String size = "";long fileLength = file.length();DecimalFormat df = new DecimalFormat("#.00");if (fileLength < 1024) {size = df.format((double) fileLength) + "BT";} else if (fileLength < 1048576) {size = df.format((double) fileLength / 1024) + "KB";} else if (fileLength < 1073741824) {size = df.format((double) fileLength / 1048576) + "MB";} else {size = df.format((double) fileLength / 1073741824) + "GB";}return size;}}

2、转码和截图处理工具类

DisposeVideoUtils.java 处理视频写入本地磁盘/服务器,将非MP4格式的格式文件进行转码写入处理,并且写入前进行视频截图

package com.sslt.utils;import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;/*** 转码和截图处理工具类* @author MINI**/
public class DisposeVideoUtils {private static final Logger logger = LoggerFactory.getLogger(DisposeVideoUtils.class);// 转码ffmpeg.exe工具路径private static final String FFMPEG_PATH = ResourceService.rb.getString("FFMPEG_PATH");// 转码mencoder.exe工具路径private static final String MENCODER_PATH = ResourceService.rb.getString("MENCODER_PATH");// 临时的视频存储路径,转码完成后可删除private static final String TEMPORARY_VIDEO_PATH = ResourceService.rb.getString("TEMPORARY_VIDEO_PATH");// 转码成功mp4视频存放路径private static final String TRANSCODE_VIDEO_MP4PATH = ResourceService.rb.getString("TRANSCODE_VIDEO_MP4PATH");// 转码后台的视频访问路径private String videoUrl;// 视频大小private String size;// 视频截图路径private String videoImg;public DisposeVideoUtils() {}//重构构造方法,传入视频存放路径public DisposeVideoUtils(String path) {videoUrl = path;}//set和get方法传递pathpublic String getVideoPath() {return videoUrl;}public String getSize() {return size;}public void setSize(String size) {this.size = size;}public void setVideoPath(String path) {videoUrl = path;}public String getVideoImg() {return videoImg;}public void setVideoImg(String videoImg) {this.videoImg = videoImg;}/*** 转码、截图和删除源文件功能* @param tempPath  临时源视频文件路径*/public String runConver(String tempPath) {logger.info("=================转码过程开始=====================");try {String targetExtension = ".mp4";    // 设置转换的格式boolean isDelSourseFile = true;// 转码、截图和删除源文件boolean beginConver = beginVideoConver(tempPath, targetExtension, isDelSourseFile);if (beginConver) {logger.info("=================转码过程彻底结束=====================");return videoUrl;}} catch (Exception e) {e.printStackTrace();}return null;}/*** 视频转码、截图和删除原视频处理* @param tempPath          临时源视频路径* @param targetExtension   转码成功的视频后缀名* @param isDelSourseFile   转换完成后是否删除源文件* @return*/private boolean beginVideoConver(String tempPath, String targetExtension, boolean isDelSourseFile) {File file = new File(tempPath);String fileName = file.getName();          //获取文件名+后缀名String fileNameSuffix = fileName.substring(fileName.lastIndexOf(".") + 1);   // 获取需要转码的文件后缀//执行转码机制if (process(tempPath, fileNameSuffix, targetExtension)) {//删除临时视频或转码原视频if (isDelSourseFile) {// 删除临时文件File fileDelete = new File(TEMPORARY_VIDEO_PATH);String[] tempList = fileDelete.list();File temp = null;for (int i = 0; i < tempList.length; i++) {if (TEMPORARY_VIDEO_PATH.endsWith(File.separator)) {temp = new File(TEMPORARY_VIDEO_PATH + tempList[i]);} else {temp = new File(TEMPORARY_VIDEO_PATH + File.separator + tempList[i]);}if (temp.isFile() || temp.isDirectory()) {temp.delete(); // 删除文件夹里面的文件}}}return true;} else {return false;}}/*** 实际转换视频格式的方法* @param tempPath        临时源视频文件路径* @param fileNameSuffix  源视频后缀名* @param targetExtension 转码成功的视频后缀名* @return*/private boolean process(String tempPath, String fileNameSuffix, String targetExtension) {//先判断视频的类型-返回状态码int type = checkVideoSuffix(fileNameSuffix);  boolean status = false;//根据状态码处理if (type == 0) {logger.info("ffmpeg可以转换,统一转为mp4文件");status = processVideoFormat(tempPath, targetExtension);//可以指定转换为什么格式的视频} else if (type == 1) {//如果type为1,将其他文件先转换为avi,然后在用ffmpeg转换为指定格式logger.info("ffmpeg不可以转换,先调用mencoder转码avi");String avifilepath = processAVI(tempPath);if (avifilepath == null){// 转码失败--avi文件没有得到logger.info("mencoder转码失败,未生成AVI文件");return false;}else {logger.info("生成AVI文件成功,ffmpeg开始转码:");status = processVideoFormat(avifilepath, targetExtension);}}return status;   //执行完成返回布尔类型true}/*** 转换为指定格式* ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)* @param oldfilepath     临时源视频文件路径* @param targetExtension 转码成功的视频后缀名 .xxx* @return*/private boolean processVideoFormat(String oldfilepath, String targetExtension) {logger.info("调用了ffmpeg.exe工具");// 先确保保存转码后的视频的mp4文件夹存在:TRANSCODE_VIDEO_MP4PATH-保存路径String mp4Path = TRANSCODE_VIDEO_MP4PATH + Long.toString(new Date().getTime()) + targetExtension;File tempFile = new File(TRANSCODE_VIDEO_MP4PATH);if (tempFile.exists()) {if (tempFile.isDirectory()) {logger.info("该转码后的文件夹已存在");} else {logger.info("同名的转码后的文件存在,不能创建文件夹");}} else {// 创建目录if (tempFile.mkdirs()) {logger.info("创建目录转码后的文件夹:" + TRANSCODE_VIDEO_MP4PATH + ",成功!");} else {logger.info("创建目录转码后的文件夹:" + TRANSCODE_VIDEO_MP4PATH + ",失败!");}}List<String> commend = new ArrayList<String>();commend.add(FFMPEG_PATH);      // 添加转换工具路径commend.add("-i");             // 添加参数"-i",该参数指定要转换的文件commend.add(oldfilepath);      // 添加要转换格式的视频文件的路径commend.add("-qscale");        // 指定转换的质量commend.add("6");commend.add("-ab");            // 设置音频码率commend.add("64");commend.add("-ac");            // 设置声道数commend.add("2");commend.add("-ar");            // 设置声音的采样频率commend.add("22050");commend.add("-r");             // 设置帧频commend.add("24");commend.add("-y");             // 添加参数"-y",该参数指定将覆盖已存在的文件commend.add(mp4Path);// 打印命令StringBuffer test = new StringBuffer();for (int i = 0; i < commend.size(); i++) {test.append(commend.get(i) + " ");}logger.info("ffmpeg输入的命令:" + test);try {// 多线程处理加快速度-解决rmvb数据丢失builder名称要相同ProcessBuilder builder = new ProcessBuilder();builder.command(commend);builder.redirectErrorStream(true);Process process = builder.start(); // 多线程处理加快速度-解决数据丢失// 线程处理threadSyn(process);process.waitFor();      // 进程等待机制,必须要有,否则不生成mp4!!!logger.info("生成mp4视频为:{}", mp4Path);// 生成mp4视频保存路径setVideoPath(mp4Path);logger.info("===============视频转码结束,开始截图=================");//视频转码完成,调用截图功能if (processImg(mp4Path)) {logger.info("===============截图成功===============");} else {logger.info("===============截图失败===============");}return true;} catch (Exception e) {e.printStackTrace();return false;}}/***  对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), *  可以先用(mencoder)转换为avi(ffmpeg能解析的)格式.再用ffmpeg解析为指定格式* @param oldfilepath   临时源视频文件路径* @return*/private String processAVI(String oldfilepath) {logger.info("调用了mencoder.exe工具");String tempPath = TEMPORARY_VIDEO_PATH + Long.toString(new Date().getTime());List<String> commend = new ArrayList<String>();commend.add(MENCODER_PATH);        // 指定mencoder.exe工具的位置commend.add(oldfilepath);          // 指定源视频的位置commend.add("-oac");commend.add("mp3lame");            // lavc 原mp3lamecommend.add("-lameopts");commend.add("preset=64");commend.add("-ovc");commend.add("xvid");               // mpg4(xvid),AVC(h.264/x264),只有h264才是公认的MP4标准编码,如果ck播放不了,就来调整这里commend.add("-xvidencopts");       // xvidencopts或x264encoptscommend.add("bitrate=600");        // 600或440commend.add("-of");commend.add("avi");commend.add("-o");commend.add(tempPath + ".avi");    // 存放路径+名称,生成.avi视频// 打印出转换命令StringBuffer test = new StringBuffer();for (int i = 0; i < commend.size(); i++) {test.append(commend.get(i) + " ");}logger.info("mencoder输入的命令:" + test);try {// 调用线程命令启动转码ProcessBuilder builder = new ProcessBuilder();builder.command(commend);Process process = builder.start(); // 多线程处理加快速度-解决数据丢失// 线程处理threadSyn(process);// 等Mencoder进程转换结束,再调用ffmepg进程非常重要!!!process.waitFor();logger.info("Mencoder进程结束");return tempPath + ".avi"; // 返回转为AVI以后的视频地址} catch (Exception e) {e.printStackTrace();return null;}}/*** 视频截图功能* @param sourceVideoPath 需要被截图的视频路径(包含文件名和后缀名)* @return*/public boolean processImg(String sourceVideoPath) {String imageFile = "images/videoFile/";String fileImpPath = ResourceService.rb.getString("filePath");// 先确保保存截图的文件夹存在File tempFile = new File(fileImpPath + imageFile);if (tempFile.exists()) {if (tempFile.isDirectory()) {logger.info("该截图保存文件夹存在。");} else {logger.info("同名的截图保存文件存在,不能创建文件夹。");}} else {logger.info("截图保存文件夹不存在,创建该文件夹。");tempFile.mkdir();}File file = new File(sourceVideoPath);String fileName = file.getName();                  // 获取视频文件的名称。String fileRealName = fileName.substring(0, fileName.lastIndexOf("."));           // 获取不加后缀名的视频名imageFile = imageFile + fileRealName + ".jpg";List<String> commend = new ArrayList<String>();// 第一帧: 00:00:01// 截图命令:time ffmpeg -ss 00:00:01 -i test1.flv -f image2 -y test1.jpgcommend.add(FFMPEG_PATH);          // 指定ffmpeg工具的路径commend.add("-ss");commend.add("00:00:01");           // 1是代表第1秒的时候截图commend.add("-i");commend.add(sourceVideoPath);      // 截图的视频路径commend.add("-f");commend.add("image2");commend.add("-y");commend.add(fileImpPath + imageFile); // 生成截图xxx.jpg// 打印截图命令StringBuffer test = new StringBuffer();for (int i = 0; i < commend.size(); i++) {test.append(commend.get(i) + " ");}logger.info("截图命令:" + test);// 转码后完成截图功能-还是得用线程来解决try {// 调用线程处理命令ProcessBuilder builder = new ProcessBuilder();builder.command(commend);Process process = builder.start();// 线程处理threadSyn(process);// 等Mencoder进程转换结束,再调用ffmepg进程非常重要!!!process.waitFor();setVideoImg(imageFile);// 视频大小String videoSize = FileUploadToolUtil.getSize(file);setSize(videoSize);logger.info("截图进程结束,视频大小:{}", getSize());return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 多线程处理* @param process*/public void threadSyn(Process process) {// 获取进程的标准输入流final InputStream is1 = process.getInputStream();// 获取进程的错误流final InputStream is2 = process.getErrorStream();// 启动两个线程,一个线程负责读标准输出流,另一个负责读标准错误流new Thread() {public void run() {BufferedReader br = new BufferedReader(new InputStreamReader(is1));try {String lineB = null;while ((lineB = br.readLine()) != null) {if (lineB != null) {logger.info(lineB); //必须取走线程信息避免堵塞}}} catch (IOException e) {e.printStackTrace();}// 关闭流finally {try {is1.close();} catch (IOException e) {e.printStackTrace();}}}}.start();new Thread() {public void run() {BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));try {String lineC = null;while ((lineC = br2.readLine()) != null) {if (lineC != null) {logger.info(lineC); //必须取走线程信息避免堵塞}}} catch (IOException e) {e.printStackTrace();}// 关闭流finally {try {is2.close();} catch (IOException e) {e.printStackTrace();}}}}.start();}/*** 检查文件类型,检查非MP4后缀* asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等使用ffmpeg能解析* wmv9,rm,rmvb等ffmpeg无法解析,先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式* @param suffixName 后缀名* @return*/public int checkVideoSuffix(String suffixName) {if (suffixName.equals("avi")) {return 0;} else if (suffixName.equals("mpg")) {return 0;} else if (suffixName.equals("wmv")) {return 0;} else if (suffixName.equals("3gp")) {return 0;} else if (suffixName.equals("mov")) {return 0;} else if (suffixName.equals("asf")) {return 0;} else if (suffixName.equals("asx")) {return 0;} else if (suffixName.equals("flv")) {return 0;} else if (suffixName.equals("mkv")) {return 0;} else if (suffixName.equals("wmv9")) {return 1;} else if (suffixName.equals("rm")) {return 1;} else if (suffixName.equals("rmvb")) {return 1;} else if (suffixName.equals("mp4")) {     // MP4不转码return 200;}return 9;}/*** 视频写入本地磁盘/服务器* @param file         上传文件* @param filePath     存储位置* @param fileName     文件名称* @return*/public boolean uploadVideo(MultipartFile file, String filePath, String fileName) {// 上传到本地磁盘/服务器try {logger.info("上传的视频写入本地磁盘/服务器");InputStream is = file.getInputStream();OutputStream os = new FileOutputStream(new File(filePath, fileName));int len = 0;byte[] buffer = new byte[2048];while ((len = is.read(buffer)) != -1) {os.write(buffer, 0, len);}os.close();os.flush();is.close();return true;} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return false;}}

3、实体类Entity

实体类 ShortVideo.java

package com.sslt.entity;import java.util.Date;/*** 视频资源管理Entity* * @author MINI**/
public class ShortVideo {private String id; // 视频资源idprivate String title; // 视频标题private String picture; // 视频截图private String descript; // 描述private String videoName; // 视频名称private String videoUrl; // 视频地址private String subclassId; // 资源类型IDprivate Integer clickNum; // 点击数private Integer likeNum; // 点赞数private String priority; // 优先级:1-置顶,2-推荐,3-普通private String status; // 状态:0-未审核、1-通过、2-不通过、3-下架private String size; // 视频大小private String remarks;  // 备注private String createBy;   // 创建者private Date createDate;  // 创建日期private String updateBy; // 更新者private Date updateDate;  // 更新日期public String getId() {return id;}public void setId(String id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title == null ? null : title.trim();}public String getPicture() {return picture;}public void setPicture(String picture) {this.picture = picture == null ? null : picture.trim();}public String getDescript() {return descript;}public void setDescript(String descript) {this.descript = descript == null ? null : descript.trim();}public String getVideoName() {return videoName;}public void setVideoName(String videoName) {this.videoName = videoName;}public String getVideoUrl() {return videoUrl;}public void setVideoUrl(String videoUrl) {this.videoUrl = videoUrl;}public String getSubclassId() {return subclassId;}public void setSubclassId(String subclassId) {this.subclassId = subclassId;}public Integer getClickNum() {return clickNum;}public void setClickNum(Integer clickNum) {this.clickNum = clickNum;}public Integer getLikeNum() {return likeNum;}public void setLikeNum(Integer likeNum) {this.likeNum = likeNum;}public String getPriority() {return priority;}public void setPriority(String priority) {this.priority = priority;}public String getStatus() {return status;}public void setStatus(String status) {this.status = status == null ? null : status.trim();}public String getSize() {return size;}public void setSize(String size) {this.size = size;}public String getRemarks() {return remarks;}public void setRemarks(String remarks) {this.remarks = remarks;}public String getCreateBy() {return createBy;}public void setCreateBy(String createBy) {this.createBy = createBy;}public Date getCreateDate() {return createDate;}public void setCreateDate(Date createDate) {this.createDate = createDate;}public String getUpdateBy() {return updateBy;}public void setUpdateBy(String updateBy) {this.updateBy = updateBy;}public Date getUpdateDate() {return updateDate;}public void setUpdateDate(Date updateDate) {this.updateDate = updateDate;}}

4、业务层:Service层

开发统一接口实现方法,方便于代码维护

(1)Service层接口类 ShortVideoService.java

package com.sslt.service;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.multipart.MultipartFile;import com.sslt.common.ResultBean;
import com.sslt.entity.ShortVideo;/*** 视频资源管理Service* @author MINI**/
public interface ShortVideoService {/*** 上传视频资源* @param request* @param response* @param file          上传的视频文件* @param shortVideo    资源实体类* @return*/public ResultBean insertShortVideo(HttpServletRequest request, HttpServletResponse response, MultipartFile file, ShortVideo shortVideo);}

(2)Service层接口实现类 ShortVideoServiceImpl.java

package com.sslt.service.impl;import java.io.File;
import java.util.Date;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import com.sslt.common.GlobalState;
import com.sslt.common.ResultBean;
import com.sslt.common.utils.UserUtils;
import com.sslt.entity.ShortVideo;
import com.sslt.service.ShortVideoService;
import com.sslt.utils.DisposeVideoUtils;
import com.sslt.utils.FileUploadToolUtil;/*** 视频资源管理Service实现类* * @author MINI**/
@Service
public class ShortVideoServiceImpl implements ShortVideoService {private static final Logger logger = LoggerFactory.getLogger(ShortVideoServiceImpl.class);// 上传的多格式的视频文件-作为临时路径保存,转码以后删除-路径不能写//@Value("${TEMPORARY_VIDEO_PATH}")private String TEMPORARY_VIDEO_PATH;// 转码成功mp4视频存放位置@Value("${TRANSCODE_VIDEO_MP4PATH}")private String TRANSCODE_VIDEO_MP4PATH;// 访问路径@Value("${VIDEO_FILE_URL}")private String VIDEO_FILE_URL;/*** 上传视频资源* @param request* @param response* @param file          上传的视频文件* @param shortVideo    资源实体类* @return*/@Overridepublic ResultBean insertShortVideo(HttpServletRequest request, HttpServletResponse response, MultipartFile file, ShortVideo shortVideo) {Integer status = GlobalState.RESULTSTATUS;String msg = "";// 文件校验ResultBean createFile = FileUploadToolUtil.createFile(file, request);if (GlobalState.FAILSTATUS.equals(createFile.getStatus())) {return ResultBean.build(createFile.getStatus(), createFile.getMsg());}String videoUrl = "";File tempFile = new File(TEMPORARY_VIDEO_PATH);if (tempFile.exists()) {logger.info("同名的临时文件存在,不创建文件夹");} else {//创建目录  if (tempFile.mkdirs()) {  logger.info("创建目录临时文件夹:" + TEMPORARY_VIDEO_PATH + ",成功!");  } else {  logger.info("创建目录临时文件夹:" + TEMPORARY_VIDEO_PATH + ",失败!");  }}// 获取上传视频的文件名String fileName = file.getOriginalFilename();// 获取文件后缀名String fileName_suffix = fileName.substring(fileName.lastIndexOf(".") + 1);logger.info("上传视频的后缀名:" + fileName_suffix);// 时间戳做新的文件名,避免中文乱码-重新生成filenameString temp_fileName = Long.toString(new Date().getTime());logger.info("临时视频名称为:" + temp_fileName);fileName = temp_fileName + "." + fileName_suffix;// 源视频地址+重命名后的视频名+视频后缀String tempPath = (TEMPORARY_VIDEO_PATH + fileName);logger.info("临时视频的完整文件名称:" + fileName);logger.info("临时视频的源视频完整路径为:" + tempPath);DisposeVideoUtils toVideo = new DisposeVideoUtils();// 判断是否需要转码int suffixType = toVideo.checkVideoSuffix(fileName_suffix);if (suffixType == 0 || suffixType == 1) {// 存储临时文件夹boolean videoBl = toVideo.uploadVideo(file, TEMPORARY_VIDEO_PATH, fileName);if (!videoBl) {return ResultBean.build(GlobalState.FAILSTATUS, "视频上传失败,请重试!");}//视频转码处理:asx,asf,mpg,wmv,3gp,mov,avi,wmv9,rm,rmvb等进行其他转码为mp4videoUrl = toVideo.runConver(tempPath);              // 调用转码File videoFile = new File(videoUrl);String videoFileName = videoFile.getName();          //获取视频文件名+后缀名temp_fileName = videoFileName.substring(0, videoFileName.lastIndexOf("."));     //获取不带后缀的视频文件名} else if(suffixType == 200) {logger.info("不需要转码,直接上传到本地磁盘/服务器,不需要存储临时文件");boolean videoBl = toVideo.uploadVideo(file, TRANSCODE_VIDEO_MP4PATH, fileName);if (!videoBl) {return ResultBean.build(GlobalState.FAILSTATUS, "视频上传失败,请重试!");}videoUrl = TRANSCODE_VIDEO_MP4PATH + temp_fileName + ".mp4";// 获取截图boolean processImg = toVideo.processImg(videoUrl);if (!processImg) {logger.info("不需要转码,直接上传到本地磁盘/服务器时,视频截图失败");return ResultBean.build(GlobalState.FAILSTATUS, "视频上传失败,请重试!");}} else {return ResultBean.build(GlobalState.FAILSTATUS, "视频上传失败,请重试!");}shortVideo.setVideoName(temp_fileName);       // 视频的名称shortVideo.setVideoUrl(videoUrl);             // 视频存放的地址shortVideo.setPicture(toVideo.getVideoImg()); // 视频截图shortVideo.setSize(toVideo.getSize());        // 视频大小this.insertSelective(shortVideo);             // 实现对数据的处理status = GlobalState.RESULTSTATUS;msg = "视频资源处理成功";return ResultBean.build(status, msg);}}

5、持久层:DAO层(mapper)

ShortVideoMapper.java

package com.sslt.mapper;import com.sslt.entity.ShortVideo;public interface ShortVideoMapper {public int insertSelective(ShortVideo shortVideo);}

ShortVideoMapper.xml 数据处理SQL语句

 <insert id="insertSelective" parameterType="com.sslt.entity.ShortVideo">insert into short_video<trim prefix="(" suffix=")" suffixOverrides=","><if test="id != null">id,</if><if test="title != null">title,</if><if test="picture != null">picture,</if><if test="descript != null">descript,</if><if test="videoName != null">video_name,</if><if test="videoUrl != null">video_url,</if><if test="subclassId != null">subclass_id,</if><if test="clickNum != null">click_num,</if><if test="likeNum != null">like_num,</if><if test="priority != null">priority,</if><if test="status != null">status,</if><if test="size != null">size,</if><if test="remarks != null">remarks,</if><if test="createBy != null">create_by,</if><if test="createDate != null">create_date,</if><if test="updateBy != null">update_by,</if><if test="updateDate != null">update_date,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="id != null">#{id,jdbcType=VARCHAR},</if><if test="title != null">#{title,jdbcType=VARCHAR},</if><if test="picture != null">#{picture,jdbcType=VARCHAR},</if><if test="descript != null">#{descript,jdbcType=VARCHAR},</if><if test="videoName != null">#{videoName,jdbcType=VARCHAR},</if><if test="videoUrl != null">#{videoUrl,jdbcType=VARCHAR},</if><if test="subclassId != null">#{subclassId,jdbcType=VARCHAR},</if><if test="clickNum != null">#{clickNum,jdbcType=INTEGER},</if><if test="likeNum != null">#{likeNum,jdbcType=INTEGER},</if><if test="priority != null">#{priority,jdbcType=CHAR},</if><if test="status != null">#{status,jdbcType=CHAR},</if><if test="size != null">#{size,jdbcType=VARCHAR},</if><if test="remarks != null">#{remarks,jdbcType=VARCHAR},</if><if test="createBy != null">#{createBy,jdbcType=VARCHAR},</if><if test="createDate != null">#{createDate,jdbcType=TIMESTAMP},</if><if test="updateBy != null">#{updateBy,jdbcType=VARCHAR},</if><if test="updateDate != null">#{updateDate,jdbcType=TIMESTAMP},</if></trim></insert>

6、表现层:Controller层(Handler层)

ShortVideoController.java 负责具体的业务模块流程的控制

/*** 视频资源管理Controller* @author MINI**/
@Controller
public class ShortVideoController {@Autowiredprivate ShortVideoService shortVideoService;@Autowiredprivate SubclassService subclassService;@Autowiredprivate DictService dictService;/*** 跳转视频添加页面* @param request* @param response* @param model* @param redirectAttributes* @return*/@RequestMapping(value = {"/openShortVideoData"})public String addShortVideo(HttpServletRequest request, HttpServletResponse response, Model model, RedirectAttributes redirectAttributes){String varId = request.getParameter("varId");if (StringUtils.isNotEmpty(varId)) {ShortVideo shortVideo = shortVideoService.selectByPrimaryKey(varId);model.addAttribute("shortVideo", shortVideo);}List<Subclass> subclassList = subclassService.findAllList(new Subclass());model.addAttribute("subclassList", subclassList);model.addAttribute("priorityList", dictService.findDictList(GlobalState.PRIORITY));model.addAttribute("statusList", dictService.findDictList(GlobalState.VIDEOSTATUS));return "shortVideo/openShortVideoData";}/*** 上传视频资源* @param file* @param request* @param response* @param redirectAttributes* @return*/@RequestMapping(value = "/insertShortVideo", method=RequestMethod.POST)public String insertShortVideo(@RequestParam(value="video") MultipartFile file, HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes){ShortVideo shortVideo = (ShortVideo) EntityBuilder.getEntity(request, ShortVideo.class);ResultBean result = shortVideoService.insertShortVideo(request, response, file, shortVideo);redirectAttributes.addFlashAttribute("msgState", result.getStatus());redirectAttributes.addFlashAttribute("message", result.getMsg());if (GlobalState.FAILSTATUS.equals(result.getStatus())) {redirectAttributes.addFlashAttribute("shortVideo", shortVideo);return "redirect:/openShortVideoData";}return "redirect:/allShortVideo";}}

7、视图层:View层

由于界面控制样式较多,前端代码就不沾出来,可根据业务代码参考实现功能,页面根据个人开发即可,下面是我的部分页面效果

后台视频资源上传

后台视频管理列表

8、转码工具下载

视频转码工具ffmpeg.exe和mencoder.exe

百度云盘链接: https://pan.baidu.com/s/1tE13ZxfowHZuo5KXmbgUJg 提取码: dav1

CSDN下载链接:https://download.csdn.net/download/u013526643/13060882

Java实现多种格式上传视频资源、解析视频格式、视频截图处理相关推荐

  1. java对接云点播上传视频,视频转码,播放视频,删除视频

    java对接云点播上传视频并且自动触发转码任务回调更新成m3u8格式的视频 前端拿到签名上传文件,签名加转码参数会触发转码任务,转码任务完成会回调设置的回调接口 /*** @desc:获取上传签名* ...

  2. java实现MinIO文件上传,并将视频文件截图,将视频封面及视频通过MinIo上传到服务器中

    java实现MinIO文件上传,并将视频文件截图,将视频封面及视频通过MinIo上传到服务器中 配置完毕,接下来开始代码编写. 说明 总过程分为两步. 1.配置MinIO的环境. 2.代码编写. 下面 ...

  3. java整合七牛云上传文件

    七牛云存储 七牛云(隶属于上海七牛信息技术有限公司)是国内领先的以视觉智能和数据智能为核心的企业级云计算服务商,同时也是国内知名智能视频云服务商,累计为 70 多万家企业提供服务,覆盖了国内80%网民 ...

  4. FastDFS的配置、部署与API使用解读(8)FastDFS多种文件上传接口详解(转)

    1.StorageClient与StorageClient1的区别 相信使用happy_fish的FastDFS的童鞋们,一定都熟悉StorageClient了,或者你熟悉的是StorageClien ...

  5. Java 头像剪切及上传服务器JSP 笔记

    头像存储真是个令人头疼的问题啊 效果: 视频没办法发,好不容易上传到B站结果这里告诉我格式错误 主要用到Java的JFrame文件选择器,然后用拦截方法过滤掉不是图片类型的文件. 用JFrame得到文 ...

  6. java云服务器怎么上传文件大小,java云服务器怎么上传文件大小

    java云服务器怎么上传文件大小 内容精选 换一换 SAP S/4HANA实例节点数据磁盘需要进行格式化,并挂载到相应的目录后,才能被正常使用.登录待安装SAP S/4HANA的云服务器"s ...

  7. java微信html5上传图片代码,java微信接口之四—上传素材

    一.微信上传素材接口简介 1.请求:该请求是使用post提交地址为: https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token=A ...

  8. 网页扫描图像并以pdf格式上传到服务器端

    本文描述如何通过网页驱动扫描仪.高拍仪等图像扫描设备进行图像扫描,扫描结果经编辑修改后以pdf压缩格式上传到后台java程序中进行服务器端落盘保存. 图像扫描上传如文字描述顺序所介绍,先要驱动扫描设备 ...

  9. java里面的文件上传与下载

    java里面的文件上传与下载 文件的上传与下载主要用到两种方法: 1.方法一:commons-fileupload.jar commons-io.jar apache的commons-fileuplo ...

  10. java实现多文件上传至本地服务器

    转载自  java实现多文件上传至本地服务器 博主最近在做一个内网项目,内部可以访问外部数据,但是外部访问不了内部数据,这也就造成了可能文件无法上传,所以博主另辟蹊径,在本地服务器上建立一个文件夹专门 ...

最新文章

  1. 转:在 .NET 中实现异步回调访问数据库
  2. mysql的主从复制功能_Mysql的主从复制功能
  3. (一)win7下cocos2d-x 21 + vs2010
  4. SCOM 常识概念—资源池介绍
  5. python画图-Python基础-画图:matplotlib
  6. elenium使用IE浏览器的配置方法
  7. 十七、MySQL触发器(创建、删除、查看)详解
  8. linux下面 r和 n的区别,【冷知识】关于/r与/n以及 /r/n 的区别总结
  9. 批量上传文件及进度显示
  10. django保存表单数据到数据库中
  11. JAVA设计模式初探之组合模式
  12. 几个常见翻译引擎的不完全对比
  13. linux  指令 备注
  14. 网易微专业python全栈工程师_Python学习笔记:6.3.10 flash WTF数据验证,6310flaskwtf
  15. Java 计算排列_java如何进行排列组合运算
  16. LNB investigation
  17. html圆形头像简易实现
  18. 零基础想学大数据?你需要这个完整学习路线
  19. IIc通信协议(一)
  20. Xing: The Land Beyond — 从课堂到 Steam* 的卓越之旅

热门文章

  1. ESP8266WIFI模块了解一下(新手入门级别)
  2. 风控建模九:一些特征工程方法及自动化工具小结
  3. java复制文件乱码_为什么用JAVA写的一个复制文本文档的程序复制出来文本文档乱码...
  4. java自动生成一年中工作日和休息日(公休日及假期国家法定假日)
  5. 项目管理表格模板/实用表格-项目启动
  6. SSM框架整合环境搭建
  7. 微信小程序三个实例带你入门
  8. 好好编程-物流项目03【GitHub管理】
  9. mark制图软件_mac自带的画图工具在哪?如何使用苹果电脑自带的预览工具进行画图操作...
  10. python怎么安装requests包_python怎么安装requests库