范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

SpringBoot上传文件返回进度

  导入的包    commons-fileupload    commons-fileupload    1.4   // 根据自己需要     org.projectlombok    lombok    true 进度返回类**  * @author Linux"s user: FB  * device: Windows 11  * create time: 2022/3/2  * remarks: []  */ @Data public class Progress implements Cloneable {      private long bytesRead;     private long contentLength;     private long items;      private static final Progress progress = new Progress();      public static Progress getInstance() {         return progress.clone();     }      @Override     public Progress clone() {         try {             return (Progress) super.clone();         } catch (CloneNotSupportedException e) {             throw new AssertionError();         }     } }文件上传监听器@Component public class FileUploadListener implements ProgressListener {      private final Map map = new ConcurrentHashMap<>();      private final HttpServletRequest request;      public FileUploadListener(HttpServletRequest request) {         this.request = request;     }      /**      * @param bytesRead 当前上传大小      * @param contentLength 总大小      * @param items 当前上传个数      */     @Override     public void update(long bytesRead, long contentLength, int items) {         Progress progress = Progress.getInstance();         progress.setBytesRead(bytesRead);         progress.setContentLength(contentLength);         progress.setItems(items);         // 可替换成 redis / session         map.put(request.getHeader("file"), progress);     }      public Progress getMap(String header) {         return map.get(header);     } }  文件上传解析器@Component public class CustomMultipartResolver extends CommonsMultipartResolver {      private final FileUploadListener fileUploadListener;      public CustomMultipartResolver(FileUploadListener fileUploadListener) {         this.fileUploadListener = fileUploadListener;     }      @Override     protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {         String encoding = determineEncoding(request);         FileUpload fileUpload = prepareFileUpload(encoding);         // 设置上传监听器         fileUpload.setProgressListener(fileUploadListener);         try {             List fileItems = ((ServletFileUpload)fileUpload).parseRequest(request);             return this.parseFileItems(fileItems, encoding);         } catch (FileUploadBase.SizeLimitExceededException var5) {             throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), var5);         } catch (FileUploadBase.FileSizeLimitExceededException var6) {             throw new MaxUploadSizeExceededException(fileUpload.getFileSizeMax(), var6);         } catch (FileUploadException var7) {             throw new MultipartException("Failed to parse multipart servlet request", var7);         }     } } Controller 接口@RestController public class UploadController {      private final UploadService uploadService;      public UploadController(UploadService uploadService) {         this.uploadService = uploadService;     }      @PostMapping("/upload")     public R upload (MultipartFile[] file) {         uploadService.upload(file);         return R.ok().message("上传成功");     }      @GetMapping("/progress")     public R progress (HttpServletRequest request) {         String file = request.getHeader("file");         if (StringUtils.isNullOrEmpty(file)) return R.error().message("需要 header: [file=xxx] 标识");          return R.ok().message(uploadService.getUploadDone(file) ? "上传完成" : "上传中...").data(uploadService.getProgressStyle(file));     } } Service 实现类@Service public class UploadServiceImpl implements UploadService {      private final StringBuilder stringBuilder = new StringBuilder();      private final Map map = new HashMap<>(4);      // 构造注入上传监听     private final FileUploadListener listener;      public UploadServiceImpl(FileUploadListener listener) {         this.listener = listener;     }      /**      * 返回进度参数信息      *         "progress": "[##########] 100%",      *         "item": 3,      *         "percent": 100,      *         "status": "over"      * @param header 文件标识      * @return Map      */     // 进度 Map     @Override     public Map getProgressStyle (String header) {         Progress progress = listener.getMap(header);         if (progress == null) throw new CustomException("未上传文件");          long read = progress.getBytesRead();         long percent = 0;         if (read != 0) percent = (read * 100) / progress.getContentLength();         map.put("percent", percent);         map.put("status", percent == 100 ? "over" : "active");         map.put("progress", getStyleOfCount(percent));         map.put("item", progress.getItems());         return map;     }      /**      * 判断文件是否上传文成      * @param header 文件标识      * @return true / false      */     @Override     public boolean getUploadDone(String header) {         Progress progress = listener.getMap(header);         if (progress == null) throw new CustomException("未上传文件");          return progress.getBytesRead() == progress.getContentLength();     }      /**      * 文件保存操作      * 这里做存储文件等其他操作操作      * 这里也需要返回进度的话,上面的进度需要 / 2,各记 50%      * @param file 文件      */     @Override     public void upload(MultipartFile[] file) {         Arrays.asList(file).forEach(f -> {             if (f.isEmpty()) {                 throw new CustomException("文件为空");             } else {                 System.out.println("文件名:" + f.getOriginalFilename());                 System.out.println("文件大小:" + f.getSize());                 System.out.println("文件类型:" + f.getContentType());             }         });     }      /**      * 进度样式      * @param percent 进度百分比      * @return [###       ] 30%      */     private String getStyleOfCount (long percent) {         stringBuilder.setLength(0);         stringBuilder.append("[");         for (int i = 0; i < percent / 10; i++) {             stringBuilder.append("#");         }         for (int i = 0; i < 10 - (percent / 10); i++) {             stringBuilder.append(" ");         }         stringBuilder.append("] ").append(percent).append("%");         return stringBuilder.toString();     } } 效果
  上传准备
  点击上传后,file 是文件的唯一标识,上传时也需要传入
  然后看效果(item 是文件个数)
  项目地址:
  Spring Boot 上传返回进度【最新】 - 小波博客

外卖骑手为什么被看不起,工资真的低吗?中国外卖行业已经进入一个爆发期,好像所有的东西事情都可以,我感觉好像有几百万骑手了吧,饿了吗专送,众包,美团专送,众包,点我达,京东,太多了,我也是其中的一员,饿了吗专送,95年的小巧迷你外形,声势不减的SoundpeatsAir3真无线蓝牙耳机测评体验前言蓝牙在我们的日常生活中已经占据了半壁江山,在我们的生活中有线耳机已经悄悄地退出了历史的舞台。但是,在众多的蓝牙耳机中我们应该怎么选择音质清晰,佩戴方便,功能齐全的无线蓝牙耳机呢iPhone13来了!iPhone11还值得入手吗?这几类人可以考虑大家好,我是科技君的探讨,欢迎关注我,与我一起进行科技的探讨。iPhone12一经发售,iPhone11却大销,这是为什么呢?其实很简单,一是性价比很高,iPhone11在12发售小米推出全新MIUI内测MIUI纯净模式。限时每天发放1000个名额大家好,又见面了我是每天分享数码一线资讯和专注二手数码回收的换换君(此处已添加小程序,请到今日头条客户端查看)最新消息,小米社区推出了全新的MIUI内测版本MIUI纯净模式。并开启高性价比的千元机市场还有人关注吗?现在各大手机厂商的发布会推广的都是自家的旗舰手机,动辄45000元以上。可是千元级手机还是有广泛的市场需求的,日常使用备用机或者给老人小孩使用完全可以满足追剧手游的运行了。而且现在坐拥数亿月活用户,微信还是忍不住开始收费了,你会买账吗?这个周末,一则微信拟推出聊天记录付费云存储服务的消息刷屏网络。据中国日报2021年9月4日报道,腾讯拟推出个人微信云存储付费服务,这意味着微信聊天记录可以实现云端备份和恢复。据说,TWS耳机市场份额苹果第一,小米第二今天redmi官宣了自家的新耳机redmiBuds3采用了半入耳式设计,方形充电盒,外观设计有点神似苹果的AirPods。搭载高通QCC3040芯片,支持低延迟的蓝牙5。2。新耳机iPad微信加入分屏模式,Mac微信加入锁定功能最近苹果微信进行了更新,首先iOS微信发布了8。0。13正式版,根据文件显示,这次的更新依旧是解决了一些已知问题,上面也并没有提到任何新功能。不过有网友反馈称,现在在微信的设置新消中国铁塔210万数字塔支撑数字中国从2014年成立时的100亿元资本金,到如今拥有3300亿元资产,中国铁塔股份有限公司(简称中国铁塔)担负起深化资源共享助力网络强国数字中国战略落地的使命,成为通信基础设施建设运营上海微电子光刻机在全球属于什么水平?这个问题非常好,提到光刻机,不能不说这是国人心中一个深深的痛。中芯国际(SMIC)为了发展最先进的7纳米芯片制造工艺,在2018年初,以1亿多美元向荷兰ASML订购了一台EUV紫外氢能汽车停产,新能源开发道阻且长可降解塑料袋,在降解与实用间寻平衡来源中工网工人日报创微言原标题氢能汽车停产,新能源开发道阻且长可降解塑料袋,在降解与实用间寻平衡兰海燕案例前不久,本田宣布年内将停产一款2016年上市的氢能汽车。此前,日产也宣布暂
提起折叠屏只知道三星华为?这款国产折叠屏比他们都早2月25日是华为最新一代折叠屏旗舰MateX2开售的日子,据电商数据,各个渠道的MateX2在一分钟的时间里被抢购一空,华为这一代折叠屏旗舰的产品力和集成程度被消费者的认可程度可见2020年初5G手机选哪款好?三星单模和华为双模用起来差别并不大尽管现在是2020年了,但5G的普及率还是很低,不过手机厂商却是很积极的在推出5G手机。5G普及是早晚的事,我们不妨早些入手一款5G手机坐等新的通讯时代到来吧,不过由于现在各个手机售价破万!华为P40系列正面PK苹果三星昨日,华为正式发布了华为P40系列(华为P40P40ProP40Pro),在发布会上,余承东先后调侃了高通苹果以及三星的产品。而就在今天中午,余承东又在微博上表示昨天华为P40系列三星Note20系列没有大改变?只是升级了下硬件近日,三星被曝光了今年即将发布的三星Note20系列的新机,引来了不少网友的热议和关注。竟三星每年发布的S系列和Note系列都是高端旗舰之作。不过从目前说曝光的信息来看,这款系列的10。29万起售,车长近4。9米,567座任选,解析捷途X90PLUS作为奇瑞旗下的子品牌,捷途以高性价比著称,并一直主攻SUV市场,在2021成都车展上,捷途发布了全新中型SUV捷途X90PLUS,并公布了预售价,10。29万的起售价格绝对很亲民,11。19万起售,星途追风正式上市,1。5T和1。6T两种动力9月7日,我们在星途汽车官网获悉,星途追风正式上市,新车提供1。5T和1。6T两种动力,共计5款车型,售价区间为11。1913。99万元。实际上星途追风就是之前的星途LX,它也是星别克君威降4。5万,全系标配9AT,入门车型的配置十分丰富!关注汽车行业的朋友都知道,受到芯片短缺影响,很多车企降低了产能,大部分车型的终端优惠也收窄了,比如别克君威之前的平均优惠一直保持在5万元以上,但到了8月份,它的平均优惠收缩到了4。低配不到18万,标配2。0T8AT,车长超4。9米,现代胜达值得买吗?现代胜达跟丰田汉兰达都是主打家用的中型SUV,但它们的销量却有着天壤之别,而且胜达是靠降价,汉兰达还得加价,我很反感加价,所以对汉兰达没什么好感,反而是胜达勾起了我的兴趣,目前低配不烧机油的大众车!顶配不超过20万,续航430公里,解析大众ID。3最近一年,上汽大众加快了布局新能源汽车的脚步,已经先后推出了ID。4XID。6X两款纯电动SUV,而在2021成都车展上,ID。3又迎来了首发亮相,据上汽大众销售公司总经理俞经民透别克昂科威降到15万,廉颇老矣,尚能饭否?2021年还值得入手吗?别克昂科威是一款十分经典的合资中型SUV,从2014年上市至今已经7年之久,但外观造型没什么大变化,上市之初也有过加价抢购的高光时刻,虽说现在没那么风光了,但凭借较大的优惠,如今依12。99万起售,全系换装1。5T四缸机,解析全新别克威朗ProProGS日前,全新别克威朗ProProGS正式上市,这是一次比较彻底的换代,外观内饰均有很大程度的升级,而变化最大的还要数动力系统,取消了上一代车型广为诟病的三缸机,换装了全新的1。5T四