SpringBoot实现断点续传与下载

在项目中如果存在大文件的上传或者下载功能,因为用户的网络或者其他各种问题,导致文件上传了一部分或者下载了一部分之后,无法继续了。这个时候就需要使用断点续传,再下次上传或者下载时,继续从上次失败的地方开始。

实现思路:将大文件分块进行上传,一个文件大小为1GB,我们分成10份,这样如果在上传的时候在第五份失败了,那么我们下次就从第五份开始。下载同理。

断点续传分为两部分:分块,合并。

分块

分块就是将文件分成一块一块的。

合并

将分块的文件合并成一个文件。

测试代码如下

package com.xuehceng.media;

import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;

import java.io.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;


public class BigFileTest {

    //    分快
    @Test
    void testChunk() throws IOException {
//        源文件
        File file = new File("E:\\1.mp4");
//        分块的文件目录
        String chunkPath = "E:\\chunk\\";
//        每一块的大小
        int chunkSize = 1024 * 1024 * 5; //5M
//        分成多少块(文件大小/块的大小)向上取整
        int chunkNum = (int) Math.ceil(file.length() * 1.0 / chunkSize);
//     读取文件的内容为随机访问文件流
        RandomAccessFile ran_r = new RandomAccessFile(file, "r");
//        将读取的文件写入到分块的文件目录中并且进行分块

        byte[] bytes = new byte[1024]; //缓冲区1M
        /**
         * 读1MB,写一个MB,如此不断循环,写完一个文件块,for循环继续,直到读完所有文件块
         *
         */
        for (int i = 0; i < chunkNum; i++) { //根据多少块遍历多少次,每一次循环都是写入一块文件
//            创建分块文件,文件地址为chunkPath+i
            File chunkFile = new File(chunkPath + i);
            if (chunkFile.exists()) {
                chunkFile.delete();
            }
            boolean newFile = chunkFile.createNewFile();
            if (newFile) {
                RandomAccessFile ran_rw = new RandomAccessFile(chunkFile, "rw");
                int len = -1; //读取的字节数
                while ((len = ran_r.read(bytes)) != -1) { //r.read()每次返回的都是读取的字节数,-1表示读完了
//                写入文件块
                    ran_rw.write(bytes, 0, len); //表示从0开始写,len表示写入的字节数
                    if (chunkSize == ran_rw.length()) {
                        break;
                    }
                }

            }
        }
    }

    //    合并
    @Test
    void testMerge() throws IOException {
        /**
         * 读取文件块,将文件块进行排序,然后进行合并
         */

        String chunkPath = "E:\\chunk\\"; //分块文件目录
        //获取分块文件并排序
        File[] chunkFiles = new File(chunkPath).listFiles();
        Arrays.sort(chunkFiles, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) { //排序规则 升序
                return Integer.parseInt(o1.getName()) - Integer.parseInt(o2.getName());
            }
        });
        // 创建合并文件
        File file = new File("E:\\2.mp4");
        boolean newFile = file.createNewFile(); //创建一个新的空文件
        //用于写文件的流
        RandomAccessFile raf_write = new RandomAccessFile(file, "rw");

        if (newFile) { //文件创建成功开始写
            byte[] bytes = new byte[1024]; //创建缓冲区
//            合并文件
            for (File chunkFile : chunkFiles) {
//            遍历一次读取一个文件块,将读取到的文件块写入合并文件
                int len = -1;
                RandomAccessFile r = new RandomAccessFile(chunkFile, "r");
                while ((len = r.read(bytes)) != -1) {
                    raf_write.write(bytes, 0, len);
                }
                r.close();
            }
            raf_write.close();
        }


    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值