上传图片视频

分布式文件系统MinIo

MinIO提供多个语言版本SDK的支持,下边找到java版本的文档:

地址:https://docs.min.io/docs/java-client-quickstart-guide.html

MinIO测试(上传、删除、下载)

public class MinioTest {

    MinioClient minioClient =
            MinioClient.builder()
                    .endpoint("http://192.168.101.65:9000")//对象存储服务的URL
                    //Access key就像用户ID,可以唯一标识你的账户。Secret key是你账户的密码。
                    .credentials("minioadmin", "minioadmin")
                    .build();

    @Test
    public void test_upload() throws Exception {

        //通过扩展名得到媒体资源类型 mimeType
        //根据扩展名取出mimeType
        ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(".mp4");
        String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;//通用mimeType,字节流
        if(extensionMatch!=null){
            mimeType = extensionMatch.getMimeType();
        }
        //上传文件的参数信息
        UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder()
                .bucket("testbucket")//桶
                .filename("D:\\develop\\upload\\1.mp4") //指定本地文件路径
                .object("test/01/1.mp4")//对象名 放在子目录下
                .contentType(mimeType)//设置媒体文件类型
                .build();
        //上传文件
        minioClient.uploadObject(uploadObjectArgs);
    }
    //删除文件
    @Test
    public void test_delete() throws Exception {

        //RemoveObjectArgs
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket("testbucket").object("1.mp4").build();

        //删除文件
        minioClient.removeObject(removeObjectArgs);
    }

    //查询文件 从minio中下载
    @Test
    public void test_getFile() throws Exception {

        GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket("testbucket").object("test/01/1.mp4").build();
        //查询远程服务获取到一个流对象
        FilterInputStream inputStream = minioClient.getObject(getObjectArgs);
        //指定输出流
        FileOutputStream outputStream = new FileOutputStream(new File("D:\\develop\\upload\\1a.mp4"));
        IOUtils.copy(inputStream,outputStream);

        //校验文件的完整性对文件的内容进行md5
        FileInputStream fileInputStream1 = new FileInputStream(new File("D:\\develop\\upload\\1.mp4"));
        String source_md5 = DigestUtils.md5Hex(fileInputStream1);
        FileInputStream fileInputStream = new FileInputStream(new File("D:\\develop\\upload\\1a.mp4"));
        String local_md5 = DigestUtils.md5Hex(fileInputStream);
        if(source_md5.equals(local_md5)){
            System.out.println("下载成功");
        }

    }
}

上传视频-断点续传

流程如下:

1、前端上传前先把文件分成块

2、一块一块的上传,上传中断后重新上传,已上传的分块则不用再上传

3、各分块上传完成最后在服务端合并文件

视频分块合并测试

public class BigFileTest {

    //分块测试
    @Test
    public void testChunk() throws IOException {
        //源文件
        File sourceFile = new File("D:\\develop\\upload\\1.项目背景.mp4");
        //分块文件存储路径
        String chunkFilePath = "D:\\develop\\upload\\chunk\\";
        //分块文件大小
        int chunkSize = 1024 * 1024 * 5;
        //分块文件个数
        int chunkNum = (int) Math.ceil(sourceFile.length() * 1.0 / chunkSize);
        //使用流从源文件读数据,向分块文件中写数据
        RandomAccessFile raf_r = new RandomAccessFile(sourceFile, "r");
        //缓存区
        byte[] bytes = new byte[1024];
        for (int i = 0; i < chunkNum; i++) {
            File chunkFile = new File(chunkFilePath + i);
            //分块文件写入流
            RandomAccessFile raf_rw = new RandomAccessFile(chunkFile, "rw");
            int len = -1;
            while ((len=raf_r.read(bytes))!=-1){
                raf_rw.write(bytes,0,len);
                if(chunkFile.length()>=chunkSize){
                    break;
                }
            }
            raf_rw.close();
        }
        raf_r.close();
    }
    //将分块进行合并
    @Test
    public void testMerge() throws IOException {
        //块文件目录
        File chunkFolder = new File("D:\\develop\\upload\\chunk");
        //源文件
        File sourceFile = new File("D:\\develop\\upload\\1.项目背景.mp4");
        //合并后的文件
        File mergeFile = new File("D:\\develop\\upload\\1.项目背景_2.mp4");

        //取出所有分块文件
        File[] files = chunkFolder.listFiles();
        //将数组转成list
        List<File> filesList = Arrays.asList(files);
        //对分块文件排序
        Collections.sort(filesList, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                return Integer.parseInt(o1.getName())-Integer.parseInt(o2.getName());
            }
        });
        //向合并文件写的流
        RandomAccessFile raf_rw = new RandomAccessFile(mergeFile, "rw");
        //缓存区
        byte[] bytes = new byte[1024];
        //遍历分块文件,向合并 的文件写
        for (File file : filesList) {
            //读分块的流
            RandomAccessFile raf_r = new RandomAccessFile(file, "r");
            int len = -1;
            while ((len=raf_r.read(bytes))!=-1){
                raf_rw.write(bytes,0,len);
            }
            raf_r.close();
        }
        raf_rw.close();
        //合并文件完成后对合并的文件md5校验
        FileInputStream fileInputStream_merge = new FileInputStream(mergeFile);
        FileInputStream fileInputStream_source = new FileInputStream(sourceFile);
        String md5_merge = DigestUtils.md5Hex(fileInputStream_merge);
        String md5_source = DigestUtils.md5Hex(fileInputStream_source);
        if(md5_merge.equals(md5_source)){
            System.out.println("文件合并成功");
        }
    }
}

视频上传流程

1、前端对文件进行分块。

2、前端上传分块文件前请求媒资服务检查文件是否存在,如果已经存在则不再上传。

3、如果分块文件不存在则前端开始上传

4、前端请求媒资服务上传分块。

5、媒资服务将分块上传至MinIO。

6、前端将分块上传完毕请求媒资服务合并分块。

7、媒资服务判断分块上传完成则请求MinIO合并文件。

8、合并完成校验合并后的文件是否完整,如果不完整则删除文件。

MinIo分块上传合并视频测试

//将分块文件上传到minio
    @Test
    public void uploadChunk() throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {

        for (int i = 0; i < 6; i++) {
            //上传文件的参数信息
            UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder()
                    .bucket("testbucket")//桶
                    .filename("D:\\develop\\upload\\chunk\\"+i) //指定本地文件路径
                    .object("chunk/"+i)//对象名 放在子目录下
                    .build();

            //上传文件
            minioClient.uploadObject(uploadObjectArgs);
            System.out.println("上传分块"+i+"成功");
        }

    }

    //调用minio接口合并分块
    @Test
    public void testMerge() throws Exception {

//        List<ComposeSource> sources = new ArrayList<>();
//        for (int i = 0; i < 30; i++) {
//            //指定分块文件的信息
//            ComposeSource composeSource = ComposeSource.builder().bucket("testbucket").object("chunk/" + i).build();
//            sources.add(composeSource);
//        }

        List<ComposeSource> sources = Stream.iterate(0, i -> ++i).limit(6).map(i -> ComposeSource.builder().bucket("testbucket").object("chunk/" + i).build()).collect(Collectors.toList());

        //指定合并后的objectName等信息
        ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder()
                .bucket("testbucket")
                .object("merge01.mp4")
                .sources(sources)//指定源文件
                .build();
        //合并文件,
        //报错size 1048576 must be greater than 5242880,minio默认的分块文件大小为5M
        minioClient.composeObject(composeObjectArgs);

    }
    //清除分块文件
    @Test
    public void test_removeObjects(){
        //合并分块完成将分块文件清除
        List<DeleteObject> deleteObjects = Stream.iterate(0, i -> ++i)
                .limit(6)
                .map(i -> new DeleteObject("chunk/".concat(Integer.toString(i))))
                .collect(Collectors.toList());

        RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder().bucket("testbucket").objects(deleteObjects).build();
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(removeObjectsArgs);
        results.forEach(r->{
            DeleteError deleteError = null;
            try {
                deleteError = r.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

 视频转码(avi转成mp4)

使用FFmpeg对视频进行编码

        //ffmpeg的路径
        String ffmpeg_path = "D:\\soft\\ffmpeg\\ffmpeg.exe";//ffmpeg的安装位置
        //源avi视频的路径
        String video_path = "D:\\develop\\upload\\02-概述-分库分表是什么.avi";
        //转换后mp4文件的名称
        String mp4_name = "02-概述-分库分表是什么.mp4";
        //转换后mp4文件的路径
        String mp4_path = "D:\\develop\\upload\\02-概述-分库分表是什么.mp4";
        //创建工具类对象
        Mp4VideoUtil videoUtil = new Mp4VideoUtil(ffmpeg_path,video_path,mp4_name,mp4_path);
        //开始视频转换,成功将返回success
        String s = videoUtil.generateMp4();
        System.out.println(s);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/65943.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构刷题】数组oj

前言:本文章是关于在力扣上面的数组相关面试题的讲解&#xff0c;包括:1.原地移除数组中所有的元素val&#xff0c;要求时间复杂度为O(N)&#xff0c;空间复杂度为O(1),2.删除排序数组中的重复项。3. 合并两个有序数组。一.原地移除数组中所有的元素val 题目: https://leetcod…

狂码三万字 | 三维场景点云理解与重建技术

目录 00 引言 01 点云特征提取与匹配 1.1 传统点云特征提取 1.2 点云深度学习 1.3 点云卷积 1.4 稀疏卷积 1.5 点云Transformer 1.6 点云旋转不变特征提取 1.7 点云匹配 02 场景点云语义分割 2.1 场景表征与数据集 2.1.1 室内场景表征与相关数据集 2.1.2 室外场…

电脑IP地址错误无法上网怎么办?

电脑出现IP地址错误后就将无法连接网络&#xff0c;从而无法正常访问互联网。那么当电脑出现IP地址错误时该怎么办呢&#xff1f; 确认是否禁用本地连接 你需要先确定是否禁用了本地网络连接&#xff0c;如果发现禁用&#xff0c;则将其启用即可。 启用方法&#xff1a;点击桌…

pytest-xdist分布式测试原理浅析

目录 pytest-xdist执行流程&#xff1a; pytest-xdist 模块结构&#xff1a; pytest-xdist分布式测试原理&#xff1a; pytest-xdist源码浅读&#xff1a; pytest-xdist执行流程&#xff1a; 解析命令行参数&#xff1a;pytest-xdist 会解析命令行参数&#xff0c;获取用户…

DROP USER c##xyt CASCADE > ORA-01940: 无法删除当前连接的用户

多创建了一个用户&#xff0c;想要给它删除掉 一 上执行过程&#xff0c;确实删除成功了 Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics and Real Application Testing optionsSQL> DR…

CVPR 2023 | Attention-Based Point Cloud Edge Sampling

注1:本文系“计算机视觉/三维重建论文速递”系列之一,致力于简洁清晰完整地介绍、解读计算机视觉,特别是三维重建领域最新的顶会/顶刊论文(包括但不限于 CVPR, ICCV, ECCV, NeurIPS等)。本次介绍的论文是: CVPR 2023 | Attention-Based Point Cloud Edge Sampling CVPR 2023 | …

【c语言】-- 结构体

&#x1f4d5;博主介绍&#xff1a;目前大一正在学习c语言&#xff0c;数据结构&#xff0c;计算机网络。 c语言学习&#xff0c;是为了更好的学习其他的编程语言&#xff0c;C语言是母体语言&#xff0c;是人机交互接近底层的桥梁。 本章来学习结构体。 让我们开启c语言学习之…

CTF流量题解http4.pcapng

流量分析 导出http 打开报错 验证文件头&#xff0c;发现是zip。 图常片见里文可件能的包16含进:压制缩头包部,word,pdf JPG FF D8 FF E0/FF D8 FF E1 PNG 89 50 4E 47 GIF 47 49 46 38 ZIP 50 4B 03 04 RAR 52 61 72 21 MP3 49 44 33 0 改后缀 使用工具爆破。 git clone git…

WordPress使用【前端投稿】功能时为用户怎么添加插入文章标签

在使用Wordpress做前端投稿功能的时候&#xff0c;可能需要用户填写文章标签&#xff0c;在插入文章的时候很多人不知道怎么把这些标签插入进去&#xff0c;下面这篇文章来为大家带来WordPress使用前端投稿功能时插入文章标签方法。 在Wordpress里 wp_insert_post 此函数的作…

docker菜谱大全

记录docker常用软件安装&#xff0c;感谢小马哥和杨师傅的投稿。&#x1f60e;&#x1f60e;&#x1f60e; 相关文档&#xff1a; DockerHub&#xff1a;https://hub.docker.com/Linux手册&#xff1a;https://linuxcool.com/Docker文档&#xff1a;https://docs.docker.com/Do…

探索Python异常世界:玩转异常、模块与包

文章目录 一 异常概念二 异常的捕获方法2.1 捕获异常的原因2.2 捕获常规异常2.3 捕获指定异常2.4 捕获多个异常2.5 捕获异常并输入异常信息2.6 捕获所有异常2.7 异常else2.8 异常finally 三 异常的传递四 python模块4.1 模块的导入方式4.2 自定义模块4.3 测试模块4.4 注意事项4…

金蝶云星空与旺店通WMS对接集成盘盈单查询连通商品同步接口(盘盈单=>其他入库单)

金蝶云星空与旺店通WMS对接集成盘盈单查询连通商品同步接口(盘盈单>其他入库单) 来源系统:金蝶云星空 金蝶K/3Cloud结合当今先进管理理论和数十万家国内客户最佳应用实践&#xff0c;面向事业部制、多地点、多工厂等运营协同与管控型企业及集团公司&#xff0c;提供一个通用…

python爬虫相关

目录 初识爬虫 爬虫分类 网络爬虫原理 爬虫基本工作流程 搜索引擎获取新网站的url robots.txt HTHP协议 Resquests模块 前言&#xff1a; 安装 普通请求 会话请求 response的常用方法 简单案例 aiohttp模块 使用前安装模块 具体案例 数据解析 re解析 bs4…

第2章:模型评估与选择

经验误差与泛化误差 过拟合是核心问题。 过拟合是无法避免的&#xff0c;只能尽量去缓解。 每个算法都要思考&#xff0c;是怎么缓解过拟合的&#xff1f;缓解方法什么情况下会失效&#xff1f; 模型选择 评估方法 留出法 为什么不能太小&#xff1f; 因为Mx要用来逼近M100的结…

深入理解PyTorch中的NoamOpt优化器

深入理解PyTorch中的NoamOpt优化器 作者&#xff1a;安静到无声 个人主页 今天&#xff0c;我们将深入探讨一个在自然语言处理领域广泛使用的优化器——NoamOpt。这个优化器是基于PyTorch实现的&#xff0c;并且在"Attention is All You Need"这篇论文中首次提出。…

JedisDataException DENIED Redis is running in protected mode...异常的解决办法

一. 异常现象 壹哥最近在带学生做项目的过程中&#xff0c;有学生在使用Redis的时候&#xff0c;产生了如下这样的异常信息&#xff1a; com.yyg.demo.Demo01Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: DENIED Redis is runni…

Vue项目npm run dev 启动报错TypeError: Cannot read property ‘upgrade‘ of undefined

vue项目启动报错 TypeError: Cannot read property upgrade of undefined 由于我的vue.config.js文件 里面的代理target为空导致的 修改&#xff1a; 结果就可以正常运行了 参考原文&#xff1a; vue项目运行时报Cannot read property ‘upgrade’ of undefined错误_cannot r…

Springboot中拦截GET请求获取请求参数验证合法性

目录 目的 核心方法 完整代码 创建拦截器 注册拦截器 测试效果 目的 在Springboot中创建拦截器拦截所有GET类型请求&#xff0c;获取请求参数验证内容合法性防止SQL注入&#xff08;该方法仅适用拦截GET类型请求&#xff0c;POST类型请求参数是在body中&#xff0c;所以下面…

git教程(第一次使用)

一、gitee和github区别 二、git使用 下载地址 windows&#xff1a;https://gitforwindows.org/ mac&#xff1a;http://sourceforge.net/projects/git-osx-installer/ 1.git初次运行前的配置 &#xff08;1&#xff09;配置用户信息 git config --global user.name "…

torch.functional.affine_grid的坑

问题描述&#xff1a;在用torch进行图像仿射变换的时候&#xff0c;平移始终有问题 比如现在想要让一张图对应的tensor平移0.5个图像长度 那么需要先构造一个transform_matrix&#xff0c;这里网上说的是偏移量不是像素值&#xff0c;而是归一化的比例 shift_x 0.5 shift_y…