文件上传下载、Excel 导入导出业务实战

发布时间:2026/9/25 9:01:10
文件上传下载、Excel 导入导出业务实战 文件上传下载、Excel 导入导出业务实战用户要上传头像、老板要导出报表、运营要批量导入会员——文件操作三件套是每个后端绕不开的基本功。一、文件上传基础1.1 MultipartFile 接口SpringBoot 用MultipartFile接口封装上传文件一个 HTTPmultipart/form-data请求到达后框架自动把文件部分封装为MultipartFile对象。RestControllerRequestMapping(/file)publicclassFileController{PostMapping(/upload)publicResultupload(RequestParam(file)MultipartFilefile){// 获取原始文件名StringoriginalFilenamefile.getOriginalFilename();// 获取文件大小字节longsizefile.getSize();// 获取文件类型StringcontentTypefile.getContentType();// 获取输入流InputStreaminputStreamfile.getInputStream();returnResult.ok(originalFilename 上传成功);}}1.2 上传大小限制配置SpringBoot 默认最大上传文件为 1MB超出直接报错。在application.yml中调整spring:servlet:multipart:max-file-size:50MB# 单个文件最大大小max-request-size:100MB# 整个请求最大大小多文件时二、单文件/多文件上传单文件上传用RequestParam接收多文件上传用数组或 ListPostMapping(/upload/multi)publicResultuploadMulti(RequestParam(files)MultipartFile[]files){for(MultipartFilefile:files){if(!file.isEmpty()){StringfileNameUUID.randomUUID()_file.getOriginalFilename();FiledestnewFile(D:/uploads/fileName);file.transferTo(dest);// 保存到本地磁盘}}returnResult.ok(上传成功);}文件名用 UUID 前缀防止重名覆盖transferTo()一行完成磁盘写入。三、文件下载下载本质就是读取文件流设置 HTTP 响应头后写回浏览器GetMapping(/download/{fileName})publicResponseEntityResourcedownload(PathVariableStringfileName){FilefilenewFile(D:/uploads/fileName);if(!file.exists())returnResponseEntity.notFound().build();ResourceresourcenewFileSystemResource(file);returnResponseEntity.ok().contentType(MediaType.APPLICATION_OCTET_STREAM).header(HttpHeaders.CONTENT_DISPOSITION,attachment; filename\URLEncoder.encode(fileName,UTF-8)\).body(resource);}Content-Disposition设为attachment告诉浏览器弹下载框否则浏览器会直接预览。中文文件名须URLEncoder.encode防乱码。四、Excel 导入导出EasyExcel 方案4.1 Apache POI vs EasyExcel对比维度Apache POIEasyExcel (阿里出品)内存占用全量加载到内存大文件直接 OOM逐行读取内存占用极小速度慢快号称 100M 文件 6 秒读完易用性代码量大注解式代码简洁推荐程度历史遗留维护新项目首选EasyExcel 的原理是边读边处理、用完就扔而不是 POI 那样把所有单元格数据撑爆内存。4.2 添加依赖dependencygroupIdcom.alibaba/groupIdartifactIdeasyexcel/artifactIdversion3.3.3/version/dependency4.3 导出 Excel注解模式定义实体类用ExcelProperty标注列DatapublicclassUserExcelVO{ExcelProperty(用户ID)privateLongid;ExcelProperty(用户名)privateStringusername;ExcelProperty(年龄)privateIntegerage;ExcelProperty(邮箱)privateStringemail;}导出只需一行GetMapping(/export)publicvoidexport(HttpServletResponseresponse)throwsIOException{ListUserExcelVOlistuserService.listForExport();response.setContentType(application/vnd.ms-excel);response.setCharacterEncoding(utf-8);response.setHeader(Content-Disposition,attachment; filenameURLEncoder.encode(用户列表.xlsx,UTF-8));EasyExcel.write(response.getOutputStream(),UserExcelVO.class).sheet(用户列表).doWrite(list);}4.4 导入 Excel监听器模式关键是不能让 EasyExcel 把全部数据加载完再处理要边读边入库publicclassUserExcelListenerextendsAnalysisEventListenerUserExcelVO{privateUserServiceuserService;publicUserExcelListener(UserServiceuserService){this.userServiceuserService;}Overridepublicvoidinvoke(UserExcelVOdata,AnalysisContextcontext){// 每读取一行就处理一行不是读完再处理userService.saveFromExcel(data);}OverridepublicvoiddoAfterAllAnalysed(AnalysisContextcontext){log.info(Excel 导入完成);}}Controller 层调用PostMapping(/import)publicResultimportExcel(RequestParam(file)MultipartFilefile)throwsIOException{EasyExcel.read(file.getInputStream(),UserExcelVO.class,newUserExcelListener(userService)).sheet().doRead();returnResult.ok(导入成功);}五、文件上传安全三道防线5.1 文件类型校验别信contentType客户端能伪造也别只信后缀名。用文件魔数Magic Number文件头几个字节验证privatestaticbooleanisImage(MultipartFilefile){try(InputStreamisfile.getInputStream()){byte[]headernewbyte[4];is.read(header);// JPEG: FF D8 FF, PNG: 89 50 4E 47, GIF: 47 49 46 38StringhexbytesToHex(header);returnhex.startsWith(FFD8FF)||hex.startsWith(89504E47);}catch(IOExceptione){returnfalse;}}5.2 路径穿越防护攻击者上传../../etc/passwd这类文件名如果直接拼接路径文件可能写入到系统敏感目录。解决方式取文件名时去掉路径信息只用纯文件名StringfileNameFilenameUtils.getName(file.getOriginalFilename());5.3 文件大小限制在application.yml设了max-file-size还不够要在 Controller 层也做校验防止绕过代理if(file.getSize()50*1024*1024){returnResult.fail(文件大小超过限制);}六、常见问题与解决问题原因解决大文件 OOMPOI 全量加载换 EasyExcel 监听器模式中文文件名乱码浏览器编码不一致URLEncoder.encode(filename, UTF-8)临时文件堆积文件未清理定时任务清理过期文件多文件上传 413 错误max-request-size太小调大该配置文件操作看似简单坑都在细节里。安全校验、编码处理、内存控制三者缺一不可。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询