文件上传

其实,进度条不用后端实现,很多前端的组件可以加载进度条。

  1. 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>
    
  2. 新建进程类Progress

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class Progress {
        private long bytesRead; //已读取文件的比特数
        private long contentLength;//文件总比特数
        private long items; //正读的第几个文件
    }
    
  3. 进程监听器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);
        }
    }
    
  4. 自定义文件解析器

    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);
            }
        }
    }
    
    
  5. 启动类排除加载配置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();
        }
    }
    
  6. 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

  7. 控制器

        @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;
        }
    
上次更新时间: 2024/5/7 05:59:02