Spring Boot 上传文件返回进度

导入的包


   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();
    }
}

效果

上传准备

Spring Boot 上传文件返回进度

点击上传后,file 是文件的唯一标识,上传时也需要传入

Spring Boot 上传文件返回进度

然后看效果(item 是文件个数)

Spring Boot 上传文件返回进度

Spring Boot 上传文件返回进度

Spring Boot 上传文件返回进度

项目地址:

Spring Boot 上传返回进度【最新】 - 小波博客

展开阅读全文

页面更新:2024-03-20

标签:进度   监听器   文件大小   标识   个数   大小   效果   上传   操作   文件

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top