首页 > 其他分享 >大文件传输方案

大文件传输方案

时间:2023-10-19 18:22:51浏览次数:35  
标签:方案 文件 int 文件传输 传输 File new RandomAccessFile

1.项目背景

项目后端框架是springboot,后端与后端之间需要进行文件传输,这个文件大小从几兆到10G不等,当文件太大时,传输可能存在失败超时等各种问题。所以涉及这种大文件传输时,直接传输是不可行的,需要有其他方式进行传输,传输的方式主要有两种:
1.http协议
传输的文件大小有限制,当文件越大时,传输较慢,而且会占用应用需要的内存,所以这种方式传输需要对文件进行拆分,将大文件拆分成小文件后再按小文件传输。

 

2.ftp/minio等三方传输
在接收端搭建ftp/minio等三方的文件存储服务器,然后通过接口向服务器传输数据,这种传输方式对文件大小限制较小,不需要拆分,而且文件越大,与http协议相比传输的效率是越快的。

 

2.解决方案

1.文件拆分传输
文件拆分代码:

public static void splitFile(String filePath, String outputPath){
        File file=new File(filePath);
        RandomAccessFile in=null;
        RandomAccessFile out =null;
        long length=file.length();//文件大小
        log.info("需要上传的zip文件大小为:{}kb",length/1024);
        long splitSize=50*1024*1024;//单片文件大小,50M
        long count=length%splitSize==0?(length/splitSize):(length/splitSize+1);//文件分片数
        byte[] bt=new byte[1024];
        try {
            in=new RandomAccessFile(file, "r");
            for (int i = 1; i <= count; i++) {
                out = new RandomAccessFile(new File(outputPath+"/"+file.getName()+"."+i+".part"), "rw");//定义一个可读可写且后缀名为.part的二进制分片文件
                long begin = (i-1)*splitSize;
                long end = i* splitSize;
                int len=0;
                in.seek(begin);
                while (in.getFilePointer()<end&&-1!=(len=in.read(bt))) {
                    out.write(bt, 0, len);
                }
                out.close();
            }
            log.info("文件分片成功,filePath={}",filePath);
        } catch (Exception e) {
            log.error("文件分片失败,error:", e);
        }finally {
            try {
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            } catch (IOException e) {
            }
        }
    }

文件合并代码:

public static void mergeFile(String splitDir,String newFilePath){
        File dir=new File(splitDir);//目录对象
        File[] fileArr=dir.listFiles(new FilenameFilter() {//分片文件
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".part");
            }
        });
        List<File> fileList = Arrays.asList(fileArr);
        Collections.sort(fileList, new Comparator<File>() {//根据文件名称对fileList顺序排序
            @Override
            public int compare(File o1, File o2) {
                int lastIndex11=o1.getName().lastIndexOf(".");
                int lastIndex12=o1.getName().substring(0,lastIndex11).lastIndexOf(".")+1;
                int lastIndex21=o2.getName().lastIndexOf(".");
                int lastIndex22=o2.getName().substring(0,lastIndex21).lastIndexOf(".")+1;
                int num1=Integer.parseInt(o1.getName().substring(lastIndex12,lastIndex11));
                int num2=Integer.parseInt(o2.getName().substring(lastIndex22,lastIndex21));
                return num1-num2;
            }
        });
        RandomAccessFile in=null;
        RandomAccessFile out =null;
        try {
            out=new RandomAccessFile(newFilePath, "rw");
            for(File file:fileList){//按顺序合成文件
                in=new RandomAccessFile(file, "r");
                int len=0;
                byte[] bt=new byte[1024];
                while (-1!=(len=in.read(bt))) {
                    out.write(bt, 0, len);
                }
                in.close();
            }
            log.info("文件合成成功,splitDir={},newFilePath={}", splitDir, newFilePath);
        } catch (Exception e) {
            log.error("文件合成失败,splitDir={},newFilePath={}", splitDir, newFilePath);
        }finally {
            try {
                if(in!=null){
                    in.close();
                }
                if(out!=null){
                    out.close();
                }
            } catch (IOException e) {
            }
        }
    }

2.minio/http传输
参考minio/ftp部署文档先搭建minio或者ftp服务器,使用它们提供的api即可。

3.并发问题

上面提高的文件拆分传输方案是串行传输,当传输到最后一个文件时,需要有个字段标识是最后一个,然后这次接受完数据就可以将分片的文件进行合并。但是,当传输不是串行而是并行时,文件接受的顺序不一定是发送文件的先后顺序,所以没办法根据发送顺序来决定是否合并,可以使用java的CountDownLatch来辅助,需要接受的文件个数可以通过发送端传送过来,当传送一个后CountDownLatch计数建1,当为0时执行合并。

 

参考文章:http://blog.ncmem.com/wordpress/2023/10/19/%e5%a4%a7%e6%96%87%e4%bb%b6%e4%bc%a0%e8%be%93%e6%96%b9%e6%a1%88/

欢迎入群一起讨论

 

 

标签:方案,文件,int,文件传输,传输,File,new,RandomAccessFile
From: https://www.cnblogs.com/songsu/p/17775344.html

相关文章

  • 安卓手机连接use调试解决方案
    一、确认手机的USB调试接口是打开的;----------打开开发者模式,暴击手机版本号多次,直到提示已打开开发者模式。二、使用USB线连接电脑和手机,可以首先执行adbremount(重新挂载系统分区,使系统分区重新可写)命令;三、remount成功后,可以使用adbshell命令查看设备是否连接成功;四、......
  • 智慧粮仓粮库解决方案:视频+AI识别技术赋能,守护大国粮仓
    一、需求背景我国作为世界人口大国,农产品需求量庞大,保障粮食等重要农产品安全是经济社会稳定发展的重要基础。粮食安全涉及到生产、收购、加工、储藏、销售等全产业链,既涉及新型基础设施建设,也有对软件技术等专业能力要求。伴随着互联技术的快速发展,粮仓粮库的建设与监管也迎来了......
  • windows命令行启动jar常见问题及解决方案
    windows端口被占用1查询端口netstat-ano2查询指定端口netstat-ano|findstr"端口号"3根据进程PID查询进程名称tasklist|findstr“进程PID号”4根据PID杀死任务taskkill-f-pid“进程PID号”5根据进程名称杀死任务taskkill-f-t-im“进程名称” ......
  • mysql三种方案优化 2000w 数据大表
    摘录自当我们业务数据库表中的数据越来越多,如果你也和我遇到了以下类似场景,那让我们一起来解决这个问题数据的插入,查询时长较长后续业务需求的扩展在表中新增字段影响较大表中的数据并不是所有的都为有效数据需求只查询时间区间内的评估表数据体量我们可以从表容量/磁......
  • Doris数据库BE——冷热数据方案
    新的冷热数据方案是在整合了存算分离模型的基础上建立的,其核心思路是:DORIS本地存储作为热数据的载体,而外部集群(HDFS、S3等)作为冷数据的载体。数据在导入的过程中,先作为热数据存在,存储于BE节点的本地磁盘上。当数据需要转冷的时候,为该热数据分片创建一个冷数据的副本分片,然后将数据......
  • RK3588开发笔记(二):基于方案商提供sdk搭建引入mpp和sdk的宿主机交叉编译Qt5.12.10环境
    前言  上一篇项目已经构建好了Qt,板子接入mipi屏幕也跑起来了,Qt也能正常运行了,现在需要接入定制开发的sdk,sdk中使用了硬解码等资源涉及到bsp的mpp,所以下一步就是引入mpp和sdk到Qt开发环境中,从而Qt中可以调用sdk接口进行进一步的应用结合开发了。 注意  本文公开了Q......
  • 律师必备软件Alpha系统,为专业律师提供高效解决方案!
        Alpha法律智能操作系统由iCourt开发,是一款集大数据、市场拓展、律所管理等功能于一体的智能操作系统,它旨在通过强大的法律科技赋能法律人,更快速地获取同类型案件的办理经验,进而减轻律师工作负担、提升工作效率。目前,这一系统业已成为了国内法律人士必备的软件工具。......
  • 启动引导Grub消失的修复方案
    故障现象:笔记本启动时未出现启动引导,卡在Lenovo图标界面。触发原因:磁盘空间已满,重启电脑时无法成功启动。修复方法:外接LinuxU盘启动盘,安装并执行boot-repair工具。$sudoadd-apt-repositoryppa:yannubuntu/boot-repair$sudoaptupdate$sudoaptinstallboot-repair......
  • 软件工程师转售前方案工程师,你必须知道的一些事儿
    一、售前工程师的就像一个“演员”售前方案工程师的核心任务,是让客户接受公司的技术解决方案。售前方案工程师,听起来很高大上,其实就是一个“翻译官”。客户说:“我要一个能飞的车。”我们就得翻译成:“客户需要一个具有创新设计理念的移动出行解决方案。”然后,我们就开始画图纸,写方案......
  • jdk8的项目迁移到jdk11以上的迁移方案
    用命令:jdeprscan--release11my-application.jar这里可以用jdeprscan--version看下是什么版本,我这边是17.0.5这里先得到一个已经被jdk8编译打包好的,测试没问题的jar文件,如上面的my-application.jar然后如果要升级到jdk17,可以用上面的命令,11改成17,这样就能检测项目是否使用......