文件上传
其实,进度条不用后端实现,很多前端的组件可以加载进度条。
pom.xml 增加
<!--添加文件上传支持--> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency>
新建进程类
Progress
@Data @Builder @NoArgsConstructor @AllArgsConstructor public class Progress { private long bytesRead; //已读取文件的比特数 private long contentLength;//文件总比特数 private long items; //正读的第几个文件 }
进程监听器
FileUploadProgressListener
@Component public class FileUploadProgressListener implements ProgressListener { private HttpSession session; public void setSession(HttpSession session){ this.session=session; Progress status = new Progress();//保存上传状态 session.setAttribute("status", status); } @Override public void update(long bytesRead, long contentLength, int items) { Progress status = (Progress) session.getAttribute("status"); status.setBytesRead(bytesRead); status.setContentLength(contentLength); status.setItems(items); } }
自定义文件解析器
public class CustomMultipartResolver extends CommonsMultipartResolver { // 注入第二步写的FileUploadProgressListener @Autowired private FileUploadProgressListener progressListener; public void setFileUploadProgressListener(FileUploadProgressListener progressListener){ this.progressListener = progressListener; } @Override public MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException { String encoding = determineEncoding(request); FileUpload fileUpload = prepareFileUpload(encoding); //fileUpload.setFileSizeMax(1024 * 1024 * 500);// 单个文件最大500M //fileUpload.setSizeMax(1024 * 1024 * 500);// 一次提交总文件最大500M progressListener.setSession(request.getSession());// 问文件上传进度监听器设置session用于存储上传进度 fileUpload.setProgressListener(progressListener);// 将文件上传进度监听器加入到 fileUpload 中 try{ List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request); return parseFileItems(fileItems, encoding); } catch (FileUploadBase.SizeLimitExceededException ex) { throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex); } catch (FileUploadException ex){ throw new MultipartException("Could not parse multipart servlet request", ex); } } }
启动类排除加载配置
MultipartAutoConfiguration
,同时注入MultipartResolver
@SpringBootApplication(exclude = MultipartAutoConfiguration.class) @MapperScan("com.dao") @EnableAspectJAutoProxy(exposeProxy = true) public class SpringBootMybatisApplication { public static void main(String[] args) { SpringApplication.run(SpringBootMybatisApplication.class, args); } @Bean(name = "multipartResolver") public MultipartResolver multipartResolver() { return new CustomMultipartResolver(); } }
yml 增加
spring: session: store-type: redis redis: flush-mode: immediate
Apache Commons FileUpload 组件上传文件时总是返回 null
Spring Boot中有默认的文件上传组件,在使用ServletFileUpload时需要关闭Spring Boot的默认配置 。
spring.http.multipart.enabled=false // 1.x
spring.servlet.multipart.enabled=false // 2.x
控制器
@PostMapping("/upload") public String upload(MultipartFile file) throws IOException { // 获取文件名 String fileName = file.getOriginalFilename();// 文件上传后的路径 String filePath = "D:/package_test/" + fileName; File saveFile = new File(filePath); if (!saveFile.getParentFile().exists()) { saveFile.getParentFile().mkdirs(); } Path path = Paths.get(filePath); Files.copy(file.getInputStream(), Paths.get(filePath), new StandardCopyOption[]{StandardCopyOption.REPLACE_EXISTING}); // Files.write(path, file.getBytes(), StandardOpenOption.SPARSE); return filePath; } @GetMapping("getPercent") public Integer getUploadPercent(HttpServletRequest request) { HttpSession session = request.getSession(); Progress status = (Progress) session.getAttribute("status"); logger.info("{}", (int)(status.getBytesRead() * 100.0 / status.getContentLength())); int percent = status == null ? 0 : (int) (status.getBytesRead() * 100.0 / status.getContentLength()); return percent; } /** * 重置上传进度 前端调用进度之前调用此接口 * * @param request * @return void */ @PostMapping("resetPercent") public Boolean resetPercent(HttpServletRequest request) { HttpSession session = request.getSession(); session.removeAttribute("status"); return true; }