/**
* 上传视频。http://localhost:8080/Video/upload
*/
@RequestMapping("/upload")
@ResponseBody
public R uploadPhoto(MultipartFile file) {
if (file == null) {
return R.error("请选择视频上传");
}
String fileName = file.getOriginalFilename();//获取初始文件名
int indexOf = fileName.lastIndexOf(".");
if(indexOf == -1){
return R.error("视频格式不正确");
}
String suffix = fileName.substring(indexOf);//得到文件名后缀 .mp4
if(suffix==null||suffix.equals(".")){
return R.error("视频格式不正确");
}
//.mp4
if(!(suffix.equals(".mp4"))){
return R.error("视频格式不正确");
}
// 生成随机文件名
String name = UUID.randomUUID().toString().replaceAll("-", "") + suffix;
//获取当前项目下视频保存的路径
String uploadPath = null;
try {
// c:\\a2295929271\ .....
uploadPath = new File("").getCanonicalPath();
} catch (IOException e) {
throw new RuntimeException("获取项目路径失败", e);
}
// 确定文件存放的路径
String ans = uploadPath + File.separator + "file" + File.separator + "video" + File.separator + name;
File dest = new File(ans);
try {
// 存储文件
file.transferTo(dest);
} catch (IOException e) {
throw new RuntimeException("上传文件失败,服务器发生异常!", e);
}
String result = domain + name;
return R.ok().put("url",result);
}
确实,视频传输上去了,一百多M的视频,没什么问题。。。。不知道传到服务器上有没有问题,估计应该有。
然而把视频读取到浏览器上:
/**
* 获取视频。
* http://localhost:8080/Video/load/626905be16ce4f36b033693cd61662dc.mp4
* 得到项目路径下 /file/video/48c3df11ca5f4c80bab198159e41a5de.png的图片
*/
@RequestMapping("/load/{name}")
@ResponseBody
public void loadPhoto(HttpServletResponse response,@PathVariable("name") String name) {
String videoPath = null;
FileInputStream fis = null;
OutputStream os = null ;
try {
//得到项目中视频保存的路径
videoPath = new File("").getCanonicalPath() + File.separator + "file" + File.separator + "video";
} catch (IOException e) {
throw new RuntimeException("获取项目路径失败", e);
}
videoPath += File.separator + name;
try {
fis = new FileInputStream(videoPath);
int size = fis.available(); // 得到文件大小
byte data[] = new byte[size];
fis.read(data); // 读数据
fis.close();
response.setContentType("video/mp4"); // 设置返回的文件类型
os = response.getOutputStream();
os.write(data);
os.flush();
os.close();
os = null;fis = null;
} catch (FileNotFoundException e) {
throw new RuntimeException("........文件" +videoPath + "未找到......", e);
} catch (IOException e) {
throw new RuntimeException("..文件大小读取异常..", e);
}
}
出现异常了,。。。百度说也就 是 文件过大了。
这样,百度到了一个方法:分片循环输出。
修改代码:
/**
* 获取视频。
* http://localhost:8080/Video/load/626905be16ce4f36b033693cd61662dc.mp4
* 得到项目路径下 /file/video/48c3df11ca5f4c80bab198159e41a5de.png的图片
*/
@RequestMapping("/load/{name}")
@ResponseBody
public void loadPhoto(HttpServletResponse response,@PathVariable("name") String name) {
String videoPath = null;
FileInputStream fis = null;
OutputStream os = null ;
response.setContentType("video/mp4");
try {
//得到项目中视频保存的路径
videoPath = new File("").getCanonicalPath() + File.separator + "file" + File.separator + "video";
} catch (IOException e) {
throw new RuntimeException("获取项目路径失败", e);
}
videoPath += File.separator + name;
try {
fis = new FileInputStream(videoPath);
int size = fis.available(); // 得到文件大小
os = response.getOutputStream();//得到输出流
byte[] data = new byte[1024 * 1024 * 5];// 5MB
// 5M 大小循环写出
fis.read(data); // 读数据
int len = 0;
while ((len = fis.read(data)) != -1) {
System.out.println("111111111111111");
os.write(data,0,len);
}
os.flush();
os.close();
fis.close();
os = null;
fis = null;
} catch (FileNotFoundException e) {
throw new RuntimeException("........文件" +videoPath + "未找到......", e);
} catch (IOException e) {
throw new RuntimeException("文件操作出现异常,请联系管理员", e);
}
}
仍然存在刚才的问题。。。。。。
待解决
过了两天继续写博客,问题已解决。不能一次性传递全部视频,要分段的传递
在每次的请求的头中加入 Range:bytes=xx-yy xx yy就是字节开始和结束点。
重新写了个接口:
/**
* 获取视频流
* @param response
* @param fileName 视频存放信息索引
* @return
* @author xWang
* @Date 2020-05-20
*/
@RequestMapping("/getVideo/{fileName}")
public void getVideo(HttpServletRequest request, HttpServletResponse response,@PathVariable("fileName") String fileName) {
//获取视频路径
String videoPath = null;
try {
//得到项目中视频保存的路径
videoPath = new File("").getCanonicalPath() + File.separator + "file" + File.separator + "video";
} catch (IOException e) {
throw new RuntimeException("获取项目路径失败", e);
}
videoPath += File.separator + fileName;
//视频资源存储信息
response.reset();
//获取从那个字节开始读取文件
String rangeString = request.getHeader("Range");
try {
//获取响应的输出流
OutputStream outputStream = response.getOutputStream();
File file = new File(videoPath);
if(file.exists()){
RandomAccessFile targetFile = new RandomAccessFile(file, "r");
long fileLength = targetFile.length();
//播放
if(rangeString != null){
long range = Long.parseLong(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));
//设置内容类型
response.setHeader("Content-Type", "video/mov");
//设置此次相应返回的数据长度
response.setHeader("Content-Length", String.valueOf(fileLength - range));
//设置此次相应返回的数据范围
response.setHeader("Content-Range", "bytes "+range+"-"+(fileLength-1)+"/"+fileLength);
//返回码需要为206,而不是200
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
//设定文件读取开始位置(以字节为单位)
targetFile.seek(range);
}else {//下载
//设置响应头,把文件名字设置好
response.setHeader("Content-Disposition", "attachment; filename="+fileName );
//设置文件长度
response.setHeader("Content-Length", String.valueOf(fileLength));
//解决编码问题
response.setHeader("Content-Type","application/octet-stream");
}
byte[] cache = new byte[1024 * 300];
int flag;
while ((flag = targetFile.read(cache))!=-1){
outputStream.write(cache, 0, flag);
}
}else {
String message = "file:"+fileName+" not exists";
//解决编码问题
response.setHeader("Content-Type","application/json");
outputStream.write(message.getBytes(StandardCharsets.UTF_8));
}
outputStream.flush();
outputStream.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
问题已解决。而且在安卓端访问的时候,也可以很好的变成访问在线播放的效果,给用户很好的体验。