使用okio的Throttler类实现IO限速(文件拷贝限速、文件下载限速)

背景

在开发文件流相关的应用时,为了保护磁盘使用率或者防止网络带宽被单个用户占满,需要对文件流采取限速策略,包括磁盘文件读写限速和文件下载限速。

Okio

Okio是 Square 公司开发的一个高效 I/O 库,用于简化 Java 和 Android 中的 I/O 操作。Throttler是 Okio中的一个类,主要用于限制带宽(速率限制),以防止读取或写入数据时占用过多网络或磁盘资源。
Throttler主要用于节流(throttle)。它可以配置读/写操作的最大速率(字节/秒),从而控制数据流量。例如,当你不想让某个操作占满全部带宽时,就可以使用Throttler

本地文件读取限速代码

File sourceFile = new File("/Users/mac/Downloads/test.pdf");
File sinkFile = new File("/Users/mac/Downloads/copy.pdf");
Throttler throttler = new Throttler();
// 限速为 1024KB/s
throttler.bytesPerSecond(1024 * 1024L);
StopWatch watch = new StopWatch();
watch.start();
try (
        BufferedSource source = Okio.buffer(Okio.source(sourceFile));
        BufferedSink sink = Okio.buffer(Okio.sink(sinkFile))
) {
    sink.writeAll(throttler.source(source));
} catch (Exception e) {
    e.printStackTrace();
}
watch.stop();
System.out.println("耗时: " + watch.getTotalTimeSeconds() + " 秒");

test.pdf文件大小为5.4MB,耗时打印日志:

耗时: 5.240336792 秒

使用OkHttp做客户端下载文件限速参考代码

@GetMapping("/download")
void proxy(
        @RequestHeader HttpHeaders requestHeaders,
        @RequestParam String link,
        HttpServletResponse response
) throws Exception {

    Request downloadRequest = new Request.Builder()
            .url(link) // 文件链接地址
            .headers(Headers.of(headers)) // 请求头
            .build();

    try (Response downloadResponse = client.newCall(downloadRequest).execute();
         BufferedSource source = Okio.buffer(Okio.source(downloadResponse.body().byteStream()));
         BufferedSink sink = Okio.buffer(Okio.sink(response.getOutputStream()))
    ) {

        // 重写响应头信息
        response.reset();
        // todo重写响应头


        Throttler throttler = new Throttler();
        // 下载限速为 1024KB/s
        throttler.bytesPerSecond(1024 * 1024L);
        sink.writeAll(throttler.source(source));

    } catch (Throwable e) {
        throw e;
    } finally {
        response.getOutputStream().flush();
        response.getOutputStream().close();
    }

}
posted @ 2025-06-03 20:06  codest  阅读(63)  评论(0)    收藏  举报