插件公告

本次更新:增加自定义变量

视频教程:插件视频集合

QQ群号:872707845

Skip to content

提示

突发奇想,想要在 Java 中实现一个速度限制器,限制方法的下载速度,于是就有了这篇文章。

1、编写计算延时时间类
java

public class SpeedLimiter {

    /** 速度上限(KB/s), 0=不限速 */
    private int maxRate = 1024;
    private long getMaxRateBytes(){
        return this.maxRate * 1024;
    }
    private long getLessCountBytes() {
        long lcb = getMaxRateBytes() / 10;
        if (lcb < 10240) lcb = 10240;
        return lcb;
        //return 1024l * 20;
    }
    public SpeedLimiter(int maxRate) {
        this.setMaxRate(maxRate);
    }
    public synchronized void setMaxRate(int maxRate){
        this.maxRate = Math.max(maxRate, 0);
    }
    private long totalBytes = 0;
    private long tmpCountBytes = 0;
    private final long lastTime = System.currentTimeMillis();
    /**
     * @author Ethan
     * @date 2022-11-18
     * @param len       send bytes
     * @description 计算线程延时
     * sendTime(Ms) = nowTime - lastTime;
     * workTime(Ms) = (totalBytes*1000)/(maxRate*1024)
     * delayTime(Ms) = workTime-sendTime
     **/
    public synchronized void delayNextBytes(int len) {
        totalBytes += len;
        tmpCountBytes += len;
        //未达到指定字节数跳过...
        if (tmpCountBytes < getLessCountBytes()) {
            return;
        }
        long sendTime =  System.currentTimeMillis() - lastTime;
        long workTime = (totalBytes * 1000) / getMaxRateBytes();
        long delayTime = workTime - sendTime;
        if (delayTime > 0) {
            try {
                Thread.sleep(delayTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            tmpCountBytes = 0;
        }
    }
}
2、编写测试demo
java

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;

@RestController
@RequestMapping(value = "/api/v1/download")
public class DownloadController {

    //设置一个本地文件用于下载测试, 大小约几百MB
    final String localFile = "/Users/daijunxiong/Desktop/sxmj.apk";

    /**
     * @author Ethan
     * @date 2022-11-18
     * @description 普通下载测试, 不限速!
     **/
    @GetMapping("getFile")
    public void getFile(HttpServletResponse response) {
        File file = this.getLocalFile(response, localFile);
        if (file == null || !file.exists()) {
            return;
        }
        InputStream is = null;
        OutputStream out = null;
        try {
            is = new FileInputStream(file);
            out = response.getOutputStream();
            IOUtils.copyLarge(is, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * @author Ethan
     * @date 2022-11-18
     * @description 限速下载测试, xxx KB/s
     **/
    @GetMapping("limit")
    public void limit(
            @RequestParam(value = "speed", defaultValue = "500", required = false) int speed,
            HttpServletResponse response
    ) {
        File file = this.getLocalFile(response, localFile);
        if (file == null || !file.exists()) {
            return;
        }
        BufferedInputStream bis = null;
        OutputStream out = null;

        try {
            bis = new BufferedInputStream(Files.newInputStream(file.toPath()));
            out = response.getOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            SpeedLimiter speedLimiter = new SpeedLimiter(speed);
            while ((length = bis.read(buffer)) != -1) {
                out.write(buffer, 0, length);
                speedLimiter.delayNextBytes(length);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(bis);
            IOUtils.closeQuietly(out);
        }
    }

    private File getLocalFile(HttpServletResponse response, String fullPath) {
        File file = new File(fullPath);
        Assert.isTrue(file.exists(), "文件不存在");
        String fileName = file.getName();
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setHeader("Content-Type", "application/x-zip-compressed");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        return file;
    }


}
本站访客数 人次 本站总访问量