Springboot+Minio通过分片下载解决IOS下H5没办法播放视频问题
一、环境说明
- JDK 1.8
- Springboot 2.7.5
- Minio 8.4.5
- Vue3实现的微信公众号网页
二、问题描述
当前项目是基于springboot和vue3的前后端分离架构,前端目前主要是基于H5展示在微信公众号的网页中。在实现视频上传、在线播放时遇到问题:前端同事说苹果手机播放不了视频,刚开始是统一用的video标签,安卓可以正常播放,但是苹果手机就出现“视频播放失败”。前端同事尝试换过video.js、vue3-play、html5 api、avplay、mui-player,都无法解决该问题,于是开始尝试后端寻找解决方案。
三、后端解决思路
第一次,是尝试将视频请求的Content-Disposition由attachment;filename=**改成inline;filename=**,这样视频请求可以直接在浏览器播放,而不是下载。但是依旧没有解决苹果手机视频播放失败的问题。并尝试《iOS无法播放MP4视频文件的解决方案 mp4视频iphone播放不了怎么办》在nginx中加入“add_header Accept-Ranges bytes;”,未能解决该问题。
第二次,分析网上找的视频,将该视频嵌入video是可以在苹果手机播放的。通过观察该请求,发现是有206的响应码,开始研究断点下载,最终在《05.springboot使用minio实现分段下载》、《H5 Video播放视频iOS 断点下载处理》两篇文章的启发下,通过minio分段下载解决了该问题。
四、关键知识点
对于下载请求的响应需要包含以下几个特殊属性:
Accept-Ranges: bytes 接收字节请求
Content-Length: 2 相应长度
Content-Range: bytes 0-1/18494715 bytes后面的空格不能少,0开始位置,1结束位置。“/”后面的是文件总大小长度
Content-Disposition inline表示浏览器直接使用,attachment表示下载,fileName表示下载的文件名
HttpResponse
Status Code: 206 Partial Content 指示请求已成功并且主体包含所请求的数据范围
五、后端下载方法代码片段
-
public void downloadSlice(String bucketName, String filename, HttpServletResponse response,
-
HttpServletRequest request) throws Exception{
-
if (StringUtils.isNotBlank(filename)) {
-
String range = request.getHeader("Range");
-
//获取文件信息
-
StatObjectResponse statObjectResponse = minioClient.statObject(
-
StatObjectArgs.builder().bucket(bucketName).object(filename).build());
-
//开始下载位置
-
long startByte = 0;
-
//结束下载位置
-
long endByte = statObjectResponse.size() - 1;
-
-
//有range的话
-
if (StringUtils.isNotBlank(range) && range.contains("bytes=") && range.contains("-")) {
-
range = range.substring(range.lastIndexOf("=") 1).trim();
-
String[] ranges = range.split("-");
-
try {
-
//判断range的类型
-
if (ranges.length == 1) {
-
//类型一:bytes=-2343
-
if (range.startsWith("-")) {
-
endByte = Long.parseLong(ranges[0]);
-
}
-
//类型二:bytes=2343-
-
else if (range.endsWith("-")) {
-
startByte = Long.parseLong(ranges[0]);
-
}
-
}
-
//类型三:bytes=22-2343
-
else if (ranges.length == 2) {
-
startByte = Long.parseLong(ranges[0]);
-
endByte = Long.parseLong(ranges[1]);
-
}
-
-
} catch (NumberFormatException e) {
-
startByte = 0;
-
endByte = statObjectResponse.size() - 1;
-
}
-
}
-
-
//要下载的长度
-
long contentLength = endByte - startByte 1;
-
//文件类型
-
String contentType = request.getServletContext().getMimeType(filename);
-
-
//解决下载文件时文件名乱码问题
-
byte[] fileNameBytes = filename.getBytes(StandardCharsets.UTF_8);
-
filename = new String(fileNameBytes, 0, fileNameBytes.length, StandardCharsets.ISO_8859_1);
-
-
//各种响应头设置
-
//支持断点续传,获取部分字节内容:
-
response.setHeader("Accept-Ranges", "bytes");
-
//http状态码要为206:表示获取部分内容
-
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
-
response.setContentType(contentType);
-
response.setHeader("Last-Modified", statObjectResponse.lastModified().toString());
-
//inline表示浏览器直接使用,attachment表示下载,fileName表示下载的文件名
-
response.setHeader("Content-Disposition", "inline;filename=" filename);
-
response.setHeader("Content-Length", String.valueOf(contentLength));
-
//Content-Range,格式为:[要下载的开始位置]-[结束位置]/[文件总大小]
-
response.setHeader("Content-Range", "bytes " startByte "-" endByte "/" statObjectResponse.size());
-
response.setHeader("ETag", "\"".concat(statObjectResponse.etag()).concat("\""));
-
-
try {
-
GetObjectResponse stream = minioClient.getObject(
-
GetObjectArgs.builder()
-
.bucket(statObjectResponse.bucket())
-
.object(statObjectResponse.object())
-
.offset(startByte)
-
.length(contentLength)
-
.build());
-
BufferedOutputStream os = new BufferedOutputStream(response.getOutputStream());
-
byte[] buffer = new byte[1024];
-
int len;
-
while ((len = stream.read(buffer)) != -1) {
-
os.write(buffer, 0, len);
-
}
-
os.flush();
-
os.close();
-
response.flushBuffer();
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfeijii
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01