实现前后端视频文件的断点续传功能

实现IO流拆分合并的集合功能(多个文本文件进行合并/一个视频文件切割成单个文件/多个视频流合并成单个视频文件/前后端视频文件的断点续传功能)

package com.example.yygoods.controller;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

import java.io.*;

@RestController
public class SequenceStream {
    Vector<InputStream> vectorStreams = new Vector<>();
    /*
     * 实现多个文本文件进行合并
     * Vector作用和数组类似,存储数据,功能会比数组强大,如: 可以返回枚举类型数据
     * 注释:SequenceInputStream参数必须是枚举类型的数据
     * vectorStreams.elements()返回此向量的组件的枚举
     **/
    @GetMapping("/streamMerge")
    public String streamMerge () {
        try {
            String UPLOAD_DIR = System.getProperty("user.dir");
            InputStream inputStream_a = new FileInputStream(UPLOAD_DIR + "\\1.txt");
            InputStream inputStream_b = new FileInputStream(UPLOAD_DIR + "\\2.txt");
            vectorStreams.add(inputStream_a);
            vectorStreams.add(inputStream_b);
            SequenceInputStream sis = new SequenceInputStream(vectorStreams.elements());
            OutputStream outputStream = new FileOutputStream(UPLOAD_DIR + "\\merge.txt");
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = sis.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            outputStream.close();
            sis.close();
        } catch (Exception e) {
            return "Error merging files: " + e.getMessage();
        }
        return "index";
    }
    /*
     * 实现一个视频文件切割成单个文件
     * RandomAccessFile可以在任意地方进行读写文件
     * getFilePointer():返回文件记录指针的当前位置
     * seek(long pos):将文件记录指针定位到pos位置
     **/
    @GetMapping("/splitVideo")
    public String splitVideo () {
        try {
            String UPLOAD_DIR = System.getProperty("user.dir");
            File source_file = new File(UPLOAD_DIR + "\\file.mp4");
            File chunk_file = new File(UPLOAD_DIR + "\\chunk");
            if(!chunk_file.exists()){
                chunk_file.mkdirs();
            }
            //切片大小设置为100kb
            long chunkSize = 102400;
            //分块数量
            long chunkNum = (long) Math.ceil(source_file.length() * 1.0 / chunkSize);
            System.out.println("分块总数:"+chunkNum);
            //缓冲区大小
            byte[] b = new byte[1024];
            //使用RandomAccessFile访问文件
            RandomAccessFile source_file_rf = new RandomAccessFile(source_file, "r");
            for (int i = 0; i < chunkNum; i++) {
                //创建分块文件,如果存在删除,在创建新建文件
                File file = new File(UPLOAD_DIR + "\\chunk\\" + i);
                if(file.exists()){
                    file.delete();
                }
                boolean newFile = file.createNewFile();
                // 创建成功,读取原文件把流写入到新建的新建文件中
                if (newFile) {
                    RandomAccessFile chunk_file_rf = new RandomAccessFile(file, "rw");
                    int len = -1;
                    while ((len = source_file_rf.read(b)) != -1) {
                        chunk_file_rf.write(b, 0, len);
                        if (file.length() >= chunkSize) {
                            break;
                        }
                    }
                    chunk_file_rf.close();
                }
            }
            source_file_rf.close();
        } catch (Exception e) {
            return "Error merging files: " + e.getMessage();
        }
        return "index";
    }
    /*
     * 实现多个视频流合并成单个视频文件
     **/
    @GetMapping("/mergVideo")
    public String mergVideo () {
        try {
            String UPLOAD_DIR = System.getProperty("user.dir");
            File origin_file = new File(UPLOAD_DIR + "\\file.mp4");
            File merge_file = new File(UPLOAD_DIR + "\\merge_file.mp4");
            File chunk_file = new File(UPLOAD_DIR + "\\chunk");
            if(merge_file.exists()) {
                merge_file.delete();
            }
            //创建新的合并文件
            merge_file.createNewFile();
            //使用RandomAccessFile读写文件
            RandomAccessFile raf_write = new RandomAccessFile(merge_file, "rw");
            //指针指向文件顶端
            raf_write.seek(0);
            //缓冲区
            byte[] b = new byte[1024];
            //分块列表
            File[] fileArray = chunk_file.listFiles();
            // 转成集合,便于排序
            List<File> fileList = Arrays.asList(fileArray);
            System.out.println("集合文件:" + fileList);
            // 从小到大排序
            Collections.sort(fileList, new Comparator<File>() {
                @Override
                public int compare(File o1, File o2) {
                    return Integer.parseInt(o1.getName()) - Integer.parseInt(o2.getName());
                }
            });
            System.out.println("排序的集合文件:" + fileList);
            // 遍历集合文件,读取每个文件的内容再写入到新文件中
            for (File chunkFile : fileList) {
                RandomAccessFile raf_read = new RandomAccessFile(chunkFile, "rw");
                int len = -1;
                while ((len = raf_read.read(b)) != -1) {
                    raf_write.write(b, 0, len);
                }
                raf_read.close();
            }
            raf_write.close();
            //校验文件
            FileInputStream fileInputStream = new FileInputStream(origin_file);
            FileInputStream mergeFileStream = new FileInputStream(merge_file);
            //取出原始文件的md5
            String originalMd5 = DigestUtils.md5Hex(fileInputStream);
            //取出合并文件的md5进行比较
            String mergeFileMd5 = DigestUtils.md5Hex(mergeFileStream);
            if (originalMd5.equals(mergeFileMd5)) {
                System.out.println("合并文件成功");
            } else {
                System.out.println("合并文件失败");
            }
        } catch (Exception e) {
            return "Error merging files: " + e.getMessage();
        }
        return "index";
    }
    /*
     * 实现前后端视频文件的断点续传功能
     * Vector作用和数组类似,存储数据,功能会比数组强大,如: 可以返回枚举类型数据
     * 注释:SequenceInputStream参数必须是枚举类型的数据
     * vectorStreams.elements()返回此向量的组件的枚举
     **/
    @PostMapping("/merge-files")
    public String mergeFiles(@RequestParam MultipartFile file, @RequestParam Integer index, @RequestParam Integer total, @RequestParam String name) {
        try {
            InputStream inputStream = file.getInputStream();
            vectorStreams.add(inputStream);
            if (index < total) {
                return "success" + index;
            } else {
                SequenceInputStream sis = new SequenceInputStream(vectorStreams.elements());
                // 假设你想把合并后的流保存为一个新文件
                String UPLOAD_DIR = System.getProperty("user.dir");
                File outfile = new File(UPLOAD_DIR + "\\" + name);
                FileOutputStream fos = new FileOutputStream(outfile);

                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = sis.read(buffer)) != -1) {
                    fos.write(buffer, 0, bytesRead);
                }
                sis.close();
                fos.close();
                vectorStreams.clear();
                return "success";
            }
        } catch (Exception e) {
            return "Error merging files: " + e.getMessage();
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容