Springboot+Minio通过分片下载解决IOS下H5无法播放视频问题

这篇具有很好参考价值的文章主要介绍了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      指示请求已成功并且主体包含所请求的数据范围

五、后端下载方法代码片段文章来源地址https://www.toymoban.com/news/detail-509618.html

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();
            }
        }
    }

到了这里,关于Springboot+Minio通过分片下载解决IOS下H5无法播放视频问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信H5下载文件、微信浏览器无法下载文件解决方案

    手机端的微信访问网页的时候,是禁止直接下载文件的 但是IOS端可以预览.txt/.doc/.docx/.xls/xlsx/.pdf等格式的文件,Android端在下载这些格式的文件时,可以唤起 ‘即将离开微信,在浏览器打开’ 提示 所以,根据手机微信的这些限制,考虑在下载文件时,使Android微信在下载任何

    2024年02月16日
    浏览(90)
  • MINIO服务器基于AWS S3 SDK 文件分片上传及下载(C++实现)

    安装环境依赖: 获取SDK源码并安装: 项目中CMakeLists.txt配置: SDK文档资料 C++_SDK.pdf 实现下载的整体类代码下载 具体内容如下

    2024年04月10日
    浏览(68)
  • 解决苹果手机ios系统app store无法下载讯飞有声的问题

    最近新买了一台苹果手机,更新系统以后发现“讯飞有声”无法下载,愁坏我了,我是讯飞有声的超级老客户了,很多年前就开始用了,几乎每天都使用,听一些公众号的文章。 具体什么原因导致app下架的不清楚,但是翻了一下知乎,发现可以通过爱思助手来操作。尝试了一

    2024年02月11日
    浏览(70)
  • java通过minio下载pdf附件

    2024年04月25日
    浏览(62)
  • 【minio】Ubuntu安装MinIO文件服务器并通过C++上传下载

    😏 ★,° :.☆( ̄▽ ̄)/$: .°★ 😏 这篇文章主要介绍MinIO的使用。 学其所用,用其所学。——梁启超 欢迎来到我的博客,一起学习知识,共同进步。 喜欢的朋友可以关注一下,下次更新不迷路🥞 MinIO是一种高性能、可扩展的 对象存储服务 ,它可以在私有云、公共云和边缘计

    2024年02月08日
    浏览(56)
  • springboot通过sharding-dbc按年、月分片

     springboot通过sharding-dbc按年、月分片 1、引入pom依赖 2、application.yml配置 3、分片算法 4、注意事项 (1)分片主键不能修改。 (2)分表后如果需指定表,入参需使用例如 ${tableSuf}           ${}和#{}的区别:${}参数不会携带‘’,但#{}会携带。 实施sharding-jdbc,一些非常痛的注

    2024年02月11日
    浏览(36)
  • springboot 本地/minio 附件下载优化

    本地上传大文件内存溢出 Direct buffer memory 附件下载服务端传流给前端需要将流缓存完毕才可以下载,导致大文件下载系统崩溃 后端服务采用nio本地上传到服务器指定目录,通过nginx代理提供下载 Java8出现了NIO,缓存,通道,选择器。在 写NIO程序的时候,经常使用ByteBuffer来读

    2024年02月07日
    浏览(42)
  • SpringBoot整合Minio(实现上传与下载)

    MinIO 是一款高性能、分布式的对象存储系统 . 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。 1.导入环境所需要的依赖 2.application.yml中进行minio的配置 3.MinIoConfig.class 配置类  此类主要做一些连接Minio实例化对象的配置  4.AjaxResult.cl

    2024年02月07日
    浏览(62)
  • SpringBoot整合Minio实现文件上传、下载

    SpringBoot整合Minio实现文件上传、下载: 1,介绍高性能分布式存储文件服务Minio:Minio是 基于Go语言编写的对象存储服务 , 适合于存储大容量非结构化的数据 ,例如 图片、音频、视频、日志文件、备份数据和容器/虚拟机镜像等 ,而一个对象文件可以是任意大小,从几kb到最

    2024年02月06日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包