需求:上传视频后,点击链接可以在PC和手机端播放预览,包括苹果手机

1.相关工具类

1.1文件上传工具类

package resources.util;import common.util.FileOperateUtil;
import common.util.HttpClientUtil;
import net.sf.json.JSONObject;
import org.apache.commons.httpclient.util.DateUtil;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;/*** @description:* @projectName:alumni* @see:resources.util* @author:* @createTime:2021/11/25 13:41* @version:1.0*/
public class FileUploadTool {TransfMediaTool transfMediaTool = new TransfMediaTool();// 文件最大500Mprivate static long upload_maxsize = 800 * 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"};// 允许转码的视频格式(ffmpeg)private static String[] allowFLV = {".avi", ".mpg", ".wmv", ".3gp",".mov", ".asf", ".asx", ".vob"};// 允许的视频转码格式(mencoder)private static String[] allowAVI = {".wmv9", ".rm", ".rmvb"};public JSONObject createFile(MultipartFile multipartFile, HttpServletRequest request, String staticRes, String from, String userId, String orgCode) {boolean bflag = false;String fileName = multipartFile.getOriginalFilename().toString();fileName = FileOperateUtil.produceFileName(fileName);//生成新的文件名// 判断文件不为空if (multipartFile.getSize() != 0 && !multipartFile.isEmpty()) {bflag = true;// 判断文件大小if (multipartFile.getSize() <= upload_maxsize) {bflag = true;// 文件类型判断if (this.checkFileType(fileName)) {bflag = true;} else {bflag = false;System.out.println("文件类型不允许");}} else {bflag = false;System.out.println("文件大小超范围");}} else {bflag = false;System.out.println("文件为空");}if (bflag) {String logoPathDir = staticRes + "/video/" + orgCode + "/" + from + "/" + userId + "/" + DateUtil.formatDate(new Date(), "yyyy-MM-dd" );//String logoRealPathDir = request.getSession().getServletContext().getRealPath(logoPathDir);File logoSaveFile = new File(logoPathDir);if (!logoSaveFile.exists()) {logoSaveFile.mkdirs();}String name = fileName.substring(0, fileName.lastIndexOf("."));System.out.println("文件名称:" + name);// 新的文件名String newFileName = this.getName(fileName);// 文件扩展名String fileEnd = this.getFileExt(fileName);String fileNamedirs = logoPathDir + File.separator + newFileName + fileEnd;System.out.println("保存的路径:" + fileNamedirs);File filedirs = new File(fileNamedirs);//依据路径创建的文件// 转入文件try {FileOperateUtil.inputCopy(multipartFile.getInputStream(), filedirs);// multipartFile.transferTo(filedirs);} catch (IllegalStateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}// 相对路径String fileDir = logoPathDir + newFileName + fileEnd;//String fileDir = logoPathDir + newFileName;StringBuilder builder = new StringBuilder(fileDir);String finalFileDir = builder.substring(1);// size存储为StringString size = this.getSize(filedirs);// 源文件保存路径String aviPath = logoSaveFile.getAbsolutePath();JSONObject result = new JSONObject();result.put("fileName", newFileName+fileEnd);//新文件名result.put("size", size);//大小result.put("contentType", HttpClientUtil.getMimeType(filedirs.getName()));//文件标识String localUrl = request.getContextPath() + "/down/video/" + orgCode + "/" + from + "/" + userId + "/" + DateUtil.formatDate(new Date(), "yyyy-MM-dd") + "/" + fileName;result.put("localUrl", localUrl);//路径return result;} else {return null;}} else {return null;}}/*** 文件类型判断** @param fileName* @return*/private 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;}/*** 视频类型判断(flv)** @param* @return*/private boolean checkMediaType(String fileEnd) {Iterator<String> type = Arrays.asList(allowFLV).iterator();while (type.hasNext()) {String ext = type.next();if (fileEnd.equals(ext)) {return true;}}return false;}/*** 视频类型判断(AVI)** @param* @return*/private boolean checkAVIType(String fileEnd) {Iterator<String> type = Arrays.asList(allowAVI).iterator();while (type.hasNext()) {String ext = type.next();if (fileEnd.equals(ext)) {return true;}}return false;}/*** 获取文件扩展名** @return string*/private String getFileExt(String fileName) {return fileName.substring(fileName.lastIndexOf("."));}/*** 依据原始文件名生成新文件名** @return*/private 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*/private 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.视频上传代码的实现

/*** description 视频上传* param [request, file, from, userId, orgCode]* return common.enums.ResultVO* author * createTime 2021/11/26 11:36**/@PostMapping("/video")public ResultVO uploadVideo(HttpServletRequest request, MultipartFile file, String from, String userId, String orgCode) {String message = "";JSONObject entity = null;// FileEntity entity = new FileEntity();FileUploadTool fileUploadTool = new FileUploadTool();ModelMap map = new ModelMap();try {entity = fileUploadTool.createFile(file, request, staticRes, from, userId, orgCode);if (entity != null) {//                service.saveFile(entity);message = "上传成功";map.put("entity", entity);map.put("result", message);} else {message = "上传失败";map.put("result", message);}} catch (Exception e) {e.printStackTrace();}return new ResultVO(ResultCode.SUCCESS, entity);}

3.视频下载PC播放以及手机播放的实现

 /*** description 视频下载器* param [request, response]* return common.enums.ResultVO* author * createTime 2021/11/26 11:39**/@GetMapping("/video/**")public ResultVO downVideo(HttpServletRequest request, HttpServletResponse response) throws IOException {String fileUrl = request.getRequestURI();try {fileUrl = URLDecoder.decode(fileUrl, "UTF-8");} catch (UnsupportedEncodingException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}fileUrl = fileUrl.substring(fileUrl.indexOf("/video") + 6);String imgPath = staticRes + "/video" + fileUrl;String realPath = imgPath;File tmFile = new File(realPath);if ((!tmFile.exists()) || tmFile.length() < 1) {throw new RuntimeException("文件不存在!");}try {/*response.setContentType("video/mp4");InputStream ins = FileOperateUtil.inputStreamFromFile(tmFile);OutputStream ous = response.getOutputStream();FileOperateUtil.readToOutStream(ins, ous, null);*/String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);sendVideo(request, response, tmFile, fileName);} catch (IOException e) {e.printStackTrace();}return new ResultVO(ResultCode.SUCCESS, "下载成功");}//解决苹果 使用 video 标签不能正常播放视频问题//刚开始时代码返回的视频流是在一个请求里全部返回的,而苹果的浏览器会先发一次探测请求来获取文件大小,之后再发送多次请求来分段取数据流的数据,其实这里就是一个分段上传的思想(Accept-Ranges)。有两个很重要的点就是,//第一:需要根据请求内容的不同做出不同的响应,第一次探测请求需要返回200,后面的请求需要返回206和具体数据//第二:contentType必须设置为video/mp4。private void sendVideo(HttpServletRequest request, HttpServletResponse response, File file, String fileName) throws FileNotFoundException, IOException {RandomAccessFile randomFile = new RandomAccessFile(file, "r");//只读模式long contentLength = randomFile.length();String range = request.getHeader("Range");int start = 0, end = 0;if (range != null && range.startsWith("bytes=")) {String[] values = range.split("=")[1].split("-");start = Integer.parseInt(values[0]);if (values.length > 1) {end = Integer.parseInt(values[1]);}}int requestSize = 0;if (end != 0 && end > start) {requestSize = end - start + 1;} else {requestSize = Integer.MAX_VALUE;}byte[] buffer = new byte[4096];response.setContentType("video/mp4");response.setHeader("Accept-Ranges", "bytes");response.setHeader("ETag", fileName);response.setHeader("Last-Modified", new Date().toString());//第一次请求只返回content length来让客户端请求多次实际数据if (range == null) {response.setHeader("Content-length", contentLength + "");} else {//以后的多次以断点续传的方式来返回视频数据response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//206long requestStart = 0, requestEnd = 0;String[] ranges = range.split("=");if (ranges.length > 1) {String[] rangeDatas = ranges[1].split("-");requestStart = Integer.parseInt(rangeDatas[0]);if (rangeDatas.length > 1) {requestEnd = Integer.parseInt(rangeDatas[1]);}}long length = 0;if (requestEnd > 0) {length = requestEnd - requestStart + 1;response.setHeader("Content-length", "" + length);response.setHeader("Content-Range", "bytes " + requestStart + "-" + requestEnd + "/" + contentLength);} else {length = contentLength - requestStart;response.setHeader("Content-length", "" + length);response.setHeader("Content-Range", "bytes " + requestStart + "-" + (contentLength - 1) + "/" + contentLength);}}ServletOutputStream out = response.getOutputStream();int needSize = requestSize;randomFile.seek(start);while (needSize > 0) {int len = randomFile.read(buffer);if (needSize < buffer.length) {out.write(buffer, 0, needSize);} else {out.write(buffer, 0, len);if (len < buffer.length) {break;}}needSize -= buffer.length;}randomFile.close();out.close();}

java视频上传,播放预览,解决苹果手机视频无法预览的问题相关推荐

  1. kindeditor支持视频flv, mp4格式视频上传播放

    首先声明本人用的版本为4.1.12 1.mp4视频格式上传: 修改kindeditor-all.js  _mediaImg()方法 原代码 function _mediaImg(blankPath, ...

  2. 【腾讯云的1001种玩法】 Laravel 整合微视频上传管理能力,轻松打造视频App后台...

    版权声明:本文由白宦成原创文章,转载请注明出处:  文章原文链接:https://www.qcloud.com/community/article/108597001488193402 来源:腾云阁  ...

  3. 优酷视频html代码在哪,如何把视频上传到优酷并获取视频通用代码?

    我们在网站上添加视频,一般是有两种情况,一:在非产品非文章页面上添加视频,例如首页,使用到的是组件里面的视频组件:二:在产品或文章页面上添加视频,在内容->产品/文章->添加产品/文章-& ...

  4. java短视频上传阿里云流程_短视频上传

    启动上传前需要设置上传回调,需要实现VODSVideoUploadCallback回调:vodsVideoUploadClient.uploadWithVideoAndImg(vodSessionCr ...

  5. 抖音实战~实现App端视频上传、发布、落库

    文章目录 一.API阅读 1. 选择或拍摄视频 2. 云函数API~文件上传 3. 视频截帧 二.App端视频上传流程 2.1. 上传流程图 2.2. 流程简述 三.前端源码实战 3.1. 选择/拍摄 ...

  6. b站视频上传软件操作视频教程

    b站视频上传软件操作视频教程 1.切换视频清晰度,支持等.这些网站实际上还是在用标签.不过它们不是简单地把视频文件设置为属性,而是用到了很多功能的-媒体源扩展.媒体源扩展媒体源扩展,常缩写为是的一个规 ...

  7. 多多情报通:拼多多视频上传多久审核?如何发布新品?

    视频相比于图片来说,可以更好的展示出商品的样貌.各位拼多多商家们需要想办法去设置好商品的视频.上传了以后还需要通过审核哦,那么拼多多视频上传多久审核呢? 拼多多视频上传多久审核? 一般拼多多视频审核时 ...

  8. 视频上传快手怎么去水印

    视频上传快手怎么去水印 在短视频操作中,视频修改的作用显得尤为重要,这里介绍几款常见的工具 1,批量下载软件(短视频无水印下载) 2,批量消重伪原创软件(视频深度消重伪原创处理) 歌乐软件,专业自媒体 ...

  9. 关于优酷视频上传出现的错误问题

    把视频上传到优酷之后很多视频是不完整的,或者画面很花,或者视频后半段没有声音.我开始以为是视频本身的问题,以为是视频的格式不对,但是后来我把同样的视频上传到其他的视频网站,然后结果视频很正常,没有出任 ...

  10. b站视频上传软件操作介绍

    b站视频上传软件操作介绍 b站视频上传软件可以批量导入账号.视频.标题.自动填写标题.标签.简介.可以设置时间间隔,支持ADSL拨号切换IP! b站视频上传软件主要是代替人工,模拟操作,完全解放双手, ...

最新文章

  1. 51nod 算法马拉松18 B 非010串 矩阵快速幂
  2. 基于FTP的Nordic nRF51822 OTA 教程一之修改boot区大小
  3. TSS描述符表的作用
  4. 《食堂远程下单系统》设计规格说明书
  5. ExecutorService- Future - Java多线程编程
  6. python hsv inrange 范围_仅20行代码,用python给证件照换底色
  7. python生产者消费者模式_【整理】Python生产者消费者模型代码 | 勤奋的小青蛙
  8. request.getAttribute()和request.getParameter()两个方法的区别
  9. java webservice 开发总结
  10. 【BZOJ 1082】[SCOI2005]栅栏 二分+dfs
  11. Annie——一个简洁强大的轻量级视频下载神器
  12. PPC软件测试自学,一个成功的PPC广告活动所需的五个步骤
  13. 解析 XML格式数据
  14. 十大城市11月房价止跌回升 上海涨幅最高
  15. 推荐系统----2020会议文章集锦
  16. SCI Translate 11安装教程
  17. Vue面试题分享之Vue双向绑定数据原理
  18. android控制中心实现,基于Android平台的智能家居系统控制中心的设计与实现
  19. OLT基本操作及ONU的认证
  20. 【Hive】快速入门~

热门文章

  1. Java400道面试题通关宝典助你进大厂,赶紧收藏起来!
  2. 人工智能教学解决方案
  3. 软件需求规格说明书模板
  4. JAVA使用JEP进行动态公式计算
  5. 好用的Android抓包神器 VNET
  6. 有没有测试颜色的软件,用什么软件测试显示器色彩最准:色彩校正软件
  7. 关联分析购物篮案例python_购物篮分析案例_关联分析算法_如何做销售数据分析 – 帆软...
  8. 好用的源码行数统计工具——cloc
  9. Microsoft Store 微软应用商店0x80131500解决方案
  10. Java函数式编程详解