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

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

作者: 祝家庄打烊 | 来源:发表于2024-06-02 10:57 被阅读0次

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

相关文章

网友评论

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

      本文链接:https://www.haomeiwen.com/subject/afqsqjtx.html