iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > JAVA >【java】java实现大文件的分片上传与下载(springboot+vue3)
  • 872
分享到

【java】java实现大文件的分片上传与下载(springboot+vue3)

javaspringbootspringvue 2023-08-16 15:08:18 872人浏览 泡泡鱼
摘要

文章目录 1.1 项目背景1.2 项目目标2.1 业务流程2.2 系统用例2.3 系统总体功能3.1 技术选型4.1 文件上传模块4.2 文件下载模块4.3 数据库设计5.1 大文件上传实现5.2 大文件下载实现 源码: htt

源码

  • https://gitee.com/gaode-8/big-file-upload

演示视频

  • Https://www.bilibili.com/video/BV1CA411f7np/?vd_source=1fe29350b37642fa583f709b9ae44b35

1.1 项目背景

对于超大文件上传我们可能遇到以下问题
• 大文件直接上传,占用过多内存,可能导致内存溢出甚至系统崩溃
• 受网络环境影响,可能导致传输中断,只能重新传输
• 传输时间长,用户无法知道传输进度,用户体验不佳

1.2 项目目标

对于上述问题,我们需要对文件做分片传输。分片传输就是把文件分割成许多较小的文件,然后分多次上传,最后再完成合并。

受网络环境影响,我们还要实现断点续传,以节省传输时间和资源。断点续传就是已经上传或者下载过的文件分片不再传输。

对于已经上传过的文件,可以不再上传,实现秒传。秒传就是根据文件的唯一标识,确认是否需要上传。
实现多任务上传或下载。多任务就是同时多个文件上传或下载。

2.1 业务流程

用户上传文件的流程图如图1所示,用户首先选择要上传的文件,上传过程中可以选择暂停或继续上传。
在这里插入图片描述

用户上传文件的流程图如图2所示,用户首先可以浏览可以下载的文件列表,然后点击下载,下载过程中可以选择暂停或继续下载

在这里插入图片描述

2.2 系统用例

系统用例图如图3所示,用户可以上传文件,在文件上传过程中可以查看文件的上传进度和速度,也可以暂停或开始上传;用户可以查看已经上传过的,也就是可以下载的文件列表;用户可以下载文件,在下载过程中可以查看文件下载的速度和进度,用户可以暂停或开始下载。
在这里插入图片描述

2.3 系统总体功能

系统总体功能图如图4所示,分为上传和下载。上传包括秒传,分片上传,断点续传,多任务。下载包括分片下载,断点续传,多任务。

在这里插入图片描述

3.1 技术选型

后端
• 语言:Java8
框架SpringBoot2.6
开发工具idea 2021
前端
• 语言:HTML5css3javascript
• 框架:vue3
开发工具vscode、Edge
数据库
Mysql8

4.1 文件上传模块

文件上传模块的流程图如图6所示,顺序图如图7所示
首先前端读取文件生成文件的唯一标识MD5,这里采用常用的MD5生成框架:spark-md5.js。对于大文件一次性读取比较慢,而且容易造成浏览器崩溃,因此这里采用分片读取的方式计算MD5。

然后向服务器发送请求,查看该文件时候已经上传,如果已经上传,就提示用户已经秒传。
如果数据库中没有记录该文件,就表示该文件没有上传或没有上传完成,那么服务器就查询并返回记录的chunk分片列表。

async 和 await配可以实现等待异步函数计算完成

//计算文件的md5值function computeMd5(file, uploadFile) {  return new Promise((resolve, reject) => {    //分片读取并计算md5    const chunkTotal = 100; //分片数    const chunkSize = Math.ceil(file.size / chunkTotal);    const fileReader = new FileReader();    const md5 = new SparkMD5();    let index = 0;    const loadFile = (uploadFile) => {      uploadFile.parsePercentage.value = parseInt((index / file.size) * 100);      const slice = file.slice(index, index + chunkSize);            fileReader.readAsBinaryString(slice);    };    loadFile(uploadFile);    fileReader.onload = (e) => {      md5.appendBinary(e.target.result);      if (index < file.size) {        index += chunkSize;        loadFile(uploadFile);      } else {        // md5.end() 就是文件md5码        resolve(md5.end());      }    };  });}//检查文件是否存在function checkFile(md5) {  return request({    url: "/check",    method: "get",    params: {      md5: md5,    },  });}//文件上传之前,el-upload自动触发async function beforeUpload(file) {  console.log("2.上传文件之前");  var uploadFile = {};  uploadFile.name = file.name;  uploadFile.size = file.size;  uploadFile.parsePercentage = ref(0);  uploadFile.uploadPercentage = ref(0);  uploadFile.uploadSpeed = "0 M/s";  uploadFile.chunkList = null;  uploadFile.file = file;  uploadFile.uploadingStop = false;  uploadFileList.value.push(uploadFile);  var md5 = await computeMd5(file, uploadFile);//async 和 await配可以实现等待异步函数计算完成  uploadFile.md5 = md5;  var res = await checkFile(md5);  //上传服务器检查,以确认是否秒传  var data = res.data.data;  if (!data.isUploaded) {    uploadFile.chunkList = data.chunkList;    uploadFile.needUpload = true;  } else {    uploadFile.needUpload = false;    uploadFile.uploadPercentage.value = 100;    console.log("文件已秒传");    ElMessage({      showClose: true,      message: "文件已秒传",      type: "warning",    });  }}

前端分片请求文件,如果分片编号被包含在分片列表内,就标识该分片已经上传,跳过;反之,表示还未上传,那么前端通过file的slice方法分割文件,向服务端传递。同时在页面上显示上传进度和速度。

服务端,收到前端的分片文件后,通过Java的RandoMaccess类(随机读写类),从文件的指定位置,写入指定字节,并记录chunk到数据库,如果是最后一个分片再记录file到数据库。
在这里插入图片描述

图6 文件上传流程图
在这里插入图片描述

图7 文件上传顺序图

前端代码

后端代码

package com.cugb.bigfileupload.controller;import com.cugb.bigfileupload.bean.FilePO;import com.cugb.bigfileupload.bean.Result;import com.cugb.bigfileupload.servie.ChunkService;import com.cugb.bigfileupload.servie.FileService;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.WEB.bind.annotation.*;import org.springframework.web.multipart.MultipartFile;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Objects;@RestController@CrossOriginpublic class FileController {    Logger logger = LoggerFactory.getLogger(getClass());    @Value("${file.path}")    private String filePath;    @Autowired    private FileService fileService;    @Autowired    private ChunkService chunkService;    @GetMapping("/check")    public Result checkFile(@RequestParam("md5") String md5){        logger.info("检查MD5:"+md5);        //首先检查是否有完整的文件        Boolean isUploaded = fileService.selectFileByMd5(md5);        Map data = new HashMap<>();        data.put("isUploaded",isUploaded);        //如果有,就返回秒传        if(isUploaded){            return new Result(201,"文件已经秒传",data);        }        //如果没有,就查找分片信息,并返回给前端        List chunkList = chunkService.selectChunkListByMd5(md5);        data.put("chunkList",chunkList);        return  new Result(201,"",data);    }    @PostMapping("/upload/chunk")    public Result uploadChunk(@RequestParam("chunk") MultipartFile chunk,  @RequestParam("md5") String md5,  @RequestParam("index") Integer index,  @RequestParam("chunkTotal")Integer chunkTotal,  @RequestParam("fileSize")Long fileSize,  @RequestParam("fileName")String fileName,  @RequestParam("chunkSize")Long chunkSize    ){        String[] splits = fileName.split("\\.");        String type = splits[splits.length-1];        String resultFileName = filePath+md5+"."+type;        chunkService.saveChunk(chunk,md5,index,chunkSize,resultFileName);        logger.info("上传分片:"+index +" ,"+chunkTotal+","+fileName+","+resultFileName);        if(Objects.equals(index, chunkTotal)){            FilePO filePO = new FilePO(fileName, md5, fileSize);            fileService.addFile(filePO);            chunkService.deleteChunkByMd5(md5);            return  new Result(200,"文件上传成功",index);        }else{            return new Result(201,"分片上传成功",index);        }    }    @GetMapping("/fileList")    public Result getFileList(){        logger.info("查询文件列表");        List fileList = fileService.selectFileList();        return  new Result(201,"文件列表查询成功",fileList);    }}

4.2 文件下载模块

文件下载的流程图如图8所示,顺序图如图9所示
文件下载是首先,前端向后端发送分片下载的请求,请求的responseType设为blob(Binary large Object) ,然后后端通过RandomAccess类读取指定字节的内容,再写入到响应的文件流中。

浏览器前端的请求的分片数据,会暂时保存在“C:\Users\用户名\AppData\Local\Microsoft\Edge\User Data\Default\blob_storage\”中,(请确保c盘有足够的空间),当所有分片下载完成,会合并成一个大文件(很快),分片不是放在内存中,所以不用担心文件太大是不是不行。

刷新浏览器,也会删除已经下载好的分片

当前端请求了所有的文件分片之后,再把所有的blob合并成一个blob

if (index == chunkTotal) {            var resBlob = new Blob(file.blobList, {              type: "application/octet-stream",            });            // console.log("resb", resBlob);            let url = window.URL.createObjectURL(resBlob); // 将获取的文件转化为blob格式            let a = document.createElement("a"); // 此处向下是打开一个储存位置            a.style.display = "none";            a.href = url;            // 下面两行是自己项目需要的处理,总之就是得到下载的文件名(加后缀)即可            var fileName = file.name;            a.setAttribute("download", fileName);            document.body.appendChild(a);            a.click(); //点击下载            document.body.removeChild(a); // 下载完成移除元素            window.URL.revokeObjectURL(url); // 释放掉blob对象          }

在这里插入图片描述在这里插入图片描述

图9文件上传顺序图

前端代码

后端代码

package com.cugb.bigfileupload.controller;import com.cugb.bigfileupload.servie.ChunkService;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import java.io.File;import java.io.IOException;import java.util.Objects;@Controller@CrossOriginpublic class DownLoadController {    Logger logger = LoggerFactory.getLogger(getClass());    @Value("${file.path}")    private String filePath;    @Autowired    private ChunkService chunkService;    @PostMapping("/download")    public void download(@RequestParam("md5") String md5,                           @RequestParam("fileName") String fileName,                           @RequestParam("chunkSize") Integer chunkSize,                         @RequestParam("chunkTotal") Integer chunkTotal,                           @RequestParam("index")Integer index,                         HttpServletResponse response) {        String[] splits = fileName.split("\\.");        String type = splits[splits.length - 1];        String resultFileName = filePath + md5 + "." + type;        File resultFile = new File(resultFileName);        long offset = (long) chunkSize * (index - 1);        if(Objects.equals(index, chunkTotal)){            offset = resultFile.length() -chunkSize;        }        byte[] chunk = chunkService.getChunk(index, chunkSize, resultFileName,offset);        logger.info("下载文件分片" + resultFileName + "," + index + "," + chunkSize + "," + chunk.length+","+offset);//        response.addHeader("Access-Control-Allow-Origin","Content-Disposition");        response.addHeader("Content-Disposition", "attachment;filename=" + fileName);        response.addHeader("Content-Length", "" + (chunk.length));        response.setHeader("filename", fileName);        response.setContentType("application/octet-stream");        ServletOutputStream out = null;        try {            out = response.getOutputStream();            out.write(chunk);            out.flush();            out.close();        } catch (IOException e) {            e.printStackTrace();        }    }}

4.3 数据库设计

3.1 概念结构设计
数据库设计只有俩个表,一个file表来记录已经完整上传的文件信息,一个chunk表用来记录还未上传完成的分片信息
在这里插入图片描述

5.1 大文件上传实现

上传页面如图13所示,有一个“选择上传文件”的按钮,下面是显示正在上传文件的列表
在这里插入图片描述
图13 上传页面首页

我们选择要上传的文件,确认上传,首先会显示解析进度,当解析完成后,就会开始上传,并显示上传进度和速度;同时,我们可以选择多个文件一同上传;在上传的同时我们还可以暂停上传。如图14所示

在这里插入图片描述

图14 上传文件中

当文件上传成功之后,就会弹窗提示文件上传成功。如图15所示

在这里插入图片描述

图15 文件上传成功
在这里插入图片描述

5.2 大文件下载实现

文件下载页面如图16所示,左边是可以下载文件的列表,右边是下载中的文件
在这里插入图片描述

在这里插入图片描述

当所有的分片下载完成后,前端会将所有的分片合并成一个文件。如图18所示

来源地址:https://blog.csdn.net/weixin_50799082/article/details/128547482

--结束END--

本文标题: 【java】java实现大文件的分片上传与下载(springboot+vue3)

本文链接: https://www.lsjlt.com/news/371593.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 【java】java实现大文件的分片上传与下载(springboot+vue3)
    文章目录 1.1 项目背景1.2 项目目标2.1 业务流程2.2 系统用例2.3 系统总体功能3.1 技术选型4.1 文件上传模块4.2 文件下载模块4.3 数据库设计5.1 大文件上传实现5.2 大文件下载实现 源码: htt...
    99+
    2023-08-16
    java spring boot spring vue
  • Java实现文件分片上传
    起因:最近在工作中接到了一个大文件上传下载的需求,要求将文件上传到share盘中,下载的时候根据前端传的不同条件对单个或多个文件进行打包并设置目录下载。 一开始我想着就还是用老办法直接file.transferTo(newFile)就算是大...
    99+
    2023-08-18
    Java 分片上传 文件
  • Java实现七牛云文件图片上传下载
    目录一、准备工作1.1.为什么选择七牛云?1.2.七牛云注册二、java操作七牛云对象存储下载2.1.pom.xml引入依赖2.2.上传下载具体代码三、具体业务例子(七牛云做...
    99+
    2024-04-02
  • Java实现HDFS文件上传下载
    本文实例为大家分享了利用Java实现HDFS文件上传下载的具体代码,供大家参考,具体内容如下 1、pom.xml配置 <!--配置--> <properties&g...
    99+
    2024-04-02
  • java实现文件上传和下载
    本文实例为大家分享了java实现文件上传和下载的具体代码,供大家参考,具体内容如下 文件的上传 upload:文件上传 客户端通过表单的文件域file  把客户端的文件 上...
    99+
    2024-04-02
  • 前端大文件上传与下载(分片上传)的详细过程
    目录一、问题二、解决1.第一步选择文件2.校验文件是否符合规范3.文件切片上传4.分片上传注意点5.大文件下载总结一、问题 日常业务中难免出现前端需要向后端传输大型文件的情况,这时单...
    99+
    2022-11-13
    前端文件上传和下载 前端上传文件 前端大文件上传
  • Java实现浏览器端大文件分片上传
    目录背景介绍 项目介绍 需要知识点 启动项目 项目示范 核心讲解核心原理 功能分析分块上传 秒传功能 断点续传 总结 参考文献 背景介绍   Breakpo...
    99+
    2024-04-02
  • 【SpringBoot+MyBatisPlus】文件上传与文件下载的应用与实现
    文章目录 前言一.文件上传二.改进三.文件下载四.上传图片/回显图片 前言 一次“上传文件”的点击蕴含着一轮请求,我们要做的就是针对每一次的请求进行i/o处理,并返回给前端用户 一.文...
    99+
    2023-09-08
    spring boot java mybatis
  • springboot大文件上传、分片上传、断点续传、秒传的实现
    对于大文件的处理,无论是用户端还是服务端,如果一次性进行读取发送、接收都是不可取,很容易导致内存问题。所以对于大文件上传,采用切块分段上传,从上传的效率来看,利用多线程并发上传能够达...
    99+
    2024-04-02
  • java实现文件上传下载功能
    本文实例为大家分享了java实现文件上传下载的具体代码,供大家参考,具体内容如下 1.上传单个文件 Controller控制层 import java.io.File; imp...
    99+
    2024-04-02
  • 利用Vue3+Element-plus实现大文件分片上传组件
    目录一、背景二、技术栈三、核心代码实现四、总结一、背景 实际项目中遇到需要上传几十个G的3d模型文件,传统上传就不适用了。 结合element提供的上传组件自己封装了文件分片上传的组...
    99+
    2023-01-28
    elementui分片上传 vue element ui教程 element ui 上传文件组件
  • Java怎么将大文件分片上传
    这篇文章主要介绍“Java怎么将大文件分片上传”,在日常操作中,相信很多人在Java怎么将大文件分片上传问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java怎么将大文件分片上传”的疑惑有所帮助!接下来,请跟...
    99+
    2023-07-02
  • java实现ftp文件上传下载功能
    本文实例为大家分享了ftp实现文件上传下载的具体代码,供大家参考,具体内容如下package getUrlPic;import java.io.ByteArrayInputStream;import java.io.IOException;...
    99+
    2023-05-31
    ftp 上传 下载
  • Java怎么实现HDFS文件上传下载
    今天小编给大家分享一下Java怎么实现HDFS文件上传下载的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。pom.xml配置&...
    99+
    2023-07-02
  • SpringBoot文件上传与下载功能实现详解
    目录前言1、引入Apache Commons FileUpload组件依赖2、设置上传文件大小限制3、创建选择文件视图页面4、创建控制器5、创建文件下载视图页面前言 文件上传与下载是...
    99+
    2022-11-13
    SpringBoot文件上传 SpringBoot文件下载
  • SpringBoot如何实现文件上传与下载功能
    今天小编给大家分享一下SpringBoot如何实现文件上传与下载功能的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Sprin...
    99+
    2023-07-02
  • SpringBoot怎么实现文件上传与下载功能
    这篇“SpringBoot怎么实现文件上传与下载功能”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“SpringBoot怎么实...
    99+
    2023-07-06
  • Java实现图片文件上传
    Java实现后台图片上传,将上传图片的接口进行分层,便于维护接口。 接口部分(interface) 将接口分为单图片上传以及多图片上传 public interface FileUp...
    99+
    2024-04-02
  • Java上传下载ftp文件
    在Java中连接FTP服务器可以使用Apache Commons Net库提供的FTPClient类。以下是一个简单的示例代码,演示如何连接到FTP服务器、进行文件上传和下载操作: import org.apache.commons.net...
    99+
    2023-09-03
    java apache 服务器
  • java- SFTP文件上传下载
    JSch - SFTP文件上传下载 文章目录 JSch - SFTP文件上传下载1. JSch简介2. ChannelSftp常用ApiJSch支持三种文件传输模式文件上传 put() 方法文...
    99+
    2023-09-30
    java 服务器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作