Java上传文件慢,大文件上传卡顿,请求超时怎么办?

话不多说直接上代码,代码复制过去可以直接使用

第一步:创建后端代码

package cn.leon.demo.rest;import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;/*** 分片上传文件相关接口** @author leon* @date 2021/03/19 17:40:06*/
@Slf4j
@RequestMapping("/chunk-upload")
@RestController
public class UploadFileController {/*** 文件上传路径,配置文件配置或者这里写死也行* ##fileUploadPath* file.upload.path=/Users/leon/Desktop**/@Value("${file.upload.path}")private String fileUploadPath;/*** 分片上传小文件** @param clientId 客户端ID,每个客户端每次上传时生成,保持唯一* @param chunkId  分片ID,从0开始累加,每次上保持传唯一* @param chunks   分片总数* @param file* @return java.lang.String* @author leon* @date 2021/04/07 17:16:59*/@CrossOrigin@PostMapping("/part")public Result bigFile(MultipartFile file, @RequestParam(name = "clientId", required = true) String clientId, @RequestParam(name = "chunks", required = true) Integer chunks, @RequestParam(name = "chunkId", required = true) Integer chunkId) throws Exception {log.info("开始上传分片文件,客户端ID:{},总分片数:{},分片ID:{}", clientId, chunks, chunkId);// 文件存放目录:临时目录用来存放所有分片文件SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");String dateStr = sdf.format(new Date());//临时文件目录String tempFileDir = fileUploadPath + File.separator + dateStr + clientId;File parentFileDir = new File(tempFileDir);if (!parentFileDir.exists()) {parentFileDir.mkdirs();}// 分片处理时,前台会多次调用上传接口,每次都会上传文件的一部分到后台File tempPartFile = new File(parentFileDir, clientId + "_" + chunkId + ".part");FileUtils.copyInputStreamToFile(file.getInputStream(), tempPartFile);log.info("分片文件上传成功,分片ID:{}", chunkId);return "ok";}/*** 上传分片文件完成后合并成一个大文件** @param clientId 客户端ID,每次上传时生成和分片上传时参数保持一致* @param fileName 原文件名* @return java.lang.String 返回最终保存文件路径* @author leon* @date 2021/04/07 17:13:46*/@CrossOrigin@PostMapping("/merge")public String mergeFile(@RequestParam(name = "clientId", required = true) String clientId, @RequestParam(name = "fileName", required = true) String fileName) throws Exception {log.info("开始合并文件,客户端ID:{},文件名:{}", clientId, fileName);// 文件存放目录SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");String dateStr = sdf.format(new Date());//最终文件上传目录String fileSavePath = fileUploadPath + File.separator + dateStr;//临时文件目录String tmpFileSavePath = fileSavePath + clientId;//最终文件上传文件名String newFileName = UUID.randomUUID().toString();if (fileName.indexOf(".") != -1) {newFileName += fileName.substring(fileName.lastIndexOf("."));}//创建父文件夹File parentFileDir = new File(tmpFileSavePath);if (parentFileDir.isDirectory()) {File destNewFile = new File(fileSavePath, newFileName);if (!destNewFile.exists()) {//先得到文件的上级目录,并创建上级目录,再创建文件destNewFile.getParentFile().mkdir();destNewFile.createNewFile();}//遍历"所有分片文件"到"最终文件"中,此处一定要按照顺序合并文件,不然会导致文件合并错乱不可用for (int i=0;i<parentFileDir.listFiles().length;i++) {FileOutputStream destNewFileFos = new FileOutputStream(destNewFile, true);FileUtils.copyFile(new File(parentFileDir, clientId + "_" + i + ".part"), destNewFileFos);destNewFileFos.close();}// 删除临时目录中的分片文件FileUtils.deleteDirectory(parentFileDir);}log.info("合并文件完成,客户端ID:{},文件名:{}", clientId, fileName);return fileSavePath + newFileName;}}

第二步:创建前端代码测试

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>分片上传文件测试</title><script src="http://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
</head>
<body>
<div id="uploader"><div class="btns"><input id="file" name="file" type="file"/><br><br><button id="startBtn">开始上传</button></br></br></div><div id="output"></div>
</div>
</body>
<script type="text/javascript">var status = 0;//上传状态var startDate;var page = {init: function(){$("#startBtn").click($.proxy(this.upload, this));},upload: function(){startDate = (new Date()).getTime();console.log("开始上传文件......");status = 0;var clientId = this.generateClientId();var file = $("#file")[0].files[0],  //文件对象fileName = file.name,        //文件名size = file.size;        //总大小var shardSize = 1024 * 1024,    //以1MB为一个分片// var shardSize = 500 * 1024,    //以500kb为一个分片shardCount = Math.ceil(size / shardSize);  //总片数console.log("每个分片文件1MB,总分片数:"+shardCount);// console.log("每个分片文件500kb,总分片数:"+shardCount);for(var i = 0;i < shardCount;++i){//计算每一片的起始与结束位置var start = i * shardSize,end = Math.min(size, start + shardSize);var partFile = file.slice(start,end);this.partUpload(clientId,partFile,fileName,shardCount,i);console.log("第"+i+"个分片文件上传成功");}var endDate = (new Date()).getTime();console.log("所有分片文件上传请求发送成功,总耗时:"+(endDate-startDate)+"毫秒");},partUpload:function(clientId,partFile,fileName,chunks,chunkId){//构造一个表单,FormData是HTML5新增的var  now = this;var form = new FormData();form.append("clientId", clientId);form.append("file", partFile);  //slice方法用于切出文件的一部分form.append("fileName", fileName);form.append("chunks", chunks);  //总片数form.append("chunkId", chunkId);        //当前是第几片//Ajax提交$.ajax({url: "http://localhost:8080/chunk-upload/part",type: "POST",data: form,async: true,        //异步processData: false,  //很重要,告诉jquery不要对form进行处理contentType: false,  //很重要,指定为false才能形成正确的Content-Typesuccess: function(data){status++;if(data.code == 0){$("#output").html(status+ " / " + chunks);}else{alert('出现异常:'+data.message);}if(status==chunks){var endDate = (new Date()).getTime();console.log("所有分片文件上传成功,总耗时:"+(endDate-startDate)+"毫秒")now.mergeFile(clientId,fileName);}}});},mergeFile:function(clientId,fileName){var formMerge = new FormData();formMerge.append("clientId", clientId);formMerge.append("fileName", fileName);$.ajax({url: "http://localhost:8080/chunk-upload/merge",type: "POST",data: formMerge,processData: false,  //很重要,告诉jquery不要对form进行处理contentType: false,  //很重要,指定为false才能形成正确的Content-Typessuccess: function(data){if(data.code == 0){var endDate = (new Date()).getTime();console.log("上传文件成功,总耗时:"+(endDate-startDate)+"毫秒");alert('上传成功!');}else{alert('出现异常:'+data.message);}}});},generateClientId:function(){var counter = 0;var clientId = (+new Date()).toString( 32 ),i = 0;for ( ; i < 5; i++ ) {clientId += Math.floor( Math.random() * 65535 ).toString( 32 );}return clientId + (counter++).toString( 32 );}};$(function(){page.init();});
</script>
</html>

上传文件慢,SpringBoot分片上传文件相关推荐

  1. SpringBoot分片上传、断点续传、大文件极速秒传功能(典藏版)

    SpringBoot分片上传.断点续传.大文件极速秒传功能,这篇都帮你搞定!(典藏版) Java研发军团 2023-02-03 21:00 文件上传是一个老生常谈的话题了,在文件相对比较小的情况下,可 ...

  2. 【vue】 前端 基于 vue-simple-uploader 实现大文件断点续传和分片上传

    文章目录 一.前言 二.后端部分 新建Maven 项目 后端 pom.xml 配置文件 application.yml HttpStatus.java AjaxResult.java CommonCo ...

  3. formdata上传文件_封装一个多文件断点续传、分片上传、秒传、重试机制的组件...

    本文为:多文件断点续传.分片上传.秒传.重试机制 的更新版,若想看初始版本的实现,请查看该文章. 凡是要知其然知其所以然 文件上传相信很多朋友都有遇到过,那或许你也遇到过当上传大文件时,上传时间较长, ...

  4. 大文件上传最全方案:秒传、断点续传、分片上传

    前言 文件上传是一个老生常谈的话题了,在文件相对比较小的情况下,可以直接把文件转化为字节流上传到服务器,但在文件比较大的情况下,用普通的方式进行上传,这可不是一个好的办法,毕竟很少有人会忍受,当文件上 ...

  5. 如何实现大文件上传:秒传、断点续传、分片上传

    前言 文件上传是一个老生常谈的话题了,在文件相对比较小的情况下,可以直接把文件转化为字节流上传到服务器,但在文件比较大的情况下,用普通的方式进行上传,这可不是一个好的办法,毕竟很少有人会忍受,当文件上 ...

  6. 前端大文件上传和下载(分片上传)

    前端大文件上传和下载(分片上传) 一.问题 日常业务中难免出现前端需要向后端传输大型文件的情况,这时单次的请求不能满足传输大文件的需求,就需要用到分片上传 业务需求为:用户可以上传小于20G的镜像文件 ...

  7. SpringBoot 分片上传、断点续传、秒传、直传Minio

    最近在学习,在SpringBoot上进行分片上传.断点续传.直接上传到Minio服务器上,中间也遇到的不少坑.自定义minio继承MinioClient来实现分片上传.比较适合初学者. 一.大致的流程 ...

  8. SpringBoot文件分片上传

    背景 最近好几个项目在运行过程中客户都提出文件上传大小的限制能否设置的大一些,用户经常需要上传好几个G的资料文件,如图纸,视频等,并且需要在上传大文件过程中进行优化实时展现进度条,进行技术评估后针对框 ...

  9. SpringBoot整合FFmpeg进行视频分片上传(Linux)

    SpringBoot整合FFmpeg进行视频分片上传 分片上传的核心思路: 分片上传到意义: 分片上传的原理: 准备工作: 一:下载.解压 代码展示: pom文件 yml配置 工具类 controll ...

最新文章

  1. 【ACM】 multiset 的 一些应用
  2. ODBC + WIN32 API 访问MYSQL 数据库实现简单QQ用户注册和登录 的代码分析
  3. Istio分层架构?80%的人有误解
  4. XML与JavaBean相互转换工具
  5. trailmakers未能连接服务器,Trailmakers联机版
  6. 零基础自学html5要多久?Web前端学习路线的6点建议
  7. (8)UART发送verilog与Systemverilog编码
  8. 软件测试基础 - 系统测试
  9. linux命令行安装vnc_centos 6.5 命令行方式可以用vnc连接吗
  10. 蓝桥杯 ADV-225 算法提高 9-2 文本加密
  11. 项目管理PMP高频考点复习资料(2-2)
  12. 【AS3代码】擦窗户效果(也就是流行的妄撮游戏)
  13. 技嘉B550M-AORUS-ELITE主板RAID故障与解决方案
  14. GLES2.0中文API-glShaderBinary
  15. 五一出游,“我”的隐私被扒干净了
  16. STM32单片机蓝牙APP智能鱼缸水位温度加氧定时喂食补光控制系统
  17. 图形验证码实现和判断并点击验证码切换
  18. 主板上Usb线序规则
  19. Python-断点续传
  20. python安装install for all users_win10安装py27/py36出现的问题汇总

热门文章

  1. 三层交换机和二层交换机的区别 三层交换机和路由器的区别
  2. Silverlight 上传下载之三种方式解析
  3. 采用html模板生成静态网页
  4. 英文辅音字母是除A、E、I、O、U以外的字母。本题要求编写程序,统计给定字符串中大写辅音字母的个数。
  5. MFC学习(27)CString内存泄漏的雷区——GetBuffer与ReleaseBuffer
  6. php支付宝开发之pc网站支付接入
  7. php数组根据值合并,PHP根据键值合并数组
  8. 路飞学城python开发ftp_路飞学城-Python开发-第二章
  9. 机器学习与深度学习的区别
  10. 蓝牙 舵狗 openmv通信相关