OkHttp Post 限速上传

在局域网中通过OkHttp post 上传一些大文件,测试后发现文件上传经常占满带宽,影响业务交互。在上传时需要限速。

限速可以服务端限速,也可以客户端限速。服务端限速只是延迟接受,造成TCP 缓冲区拥堵,带宽的问题并没有真正的解决。客户端限速的思路就是写Socket 限速。搜了一下资料,OkHttp 并没有提供限速的接口。

研究了一下OkHttp 的拦截器 Interceptor

一 网络访问的执行 RealCall

在RealCall 的execute 函数中调用getResponseWithInterceptorChain 函数 获取网络的Response。

RealCall.java 
 @Override protected void execute() {
      boolean signalledCallback = false;
      try {
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }

二 OkHttp Interceptor 的实现。

从代码中可以看到,拦截器是别加入到一个数组中。依次是:

  1. client.interceptors() 自定的拦截器
  2. retryAndFollowUpInterceptor
  3. BridgeInterceptor
  4. CacheInterceptor
  5. ConnectInterceptor
  6. CallServerInterceptor

顺序很重要,因为下面拦截器的执行和顺序有关。
真正的网咯访问是在 CallServerInterceptor 中

RealCall.java 
  Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterce
Tollbooth 是一个用 Go 语言编写的用来限制 HTTP 访问速度的中间件,可用来限制每个 HTTP 请求的传输速率。例如你可以不限制 / 的访问速率,但是可以针对 /login 限制每个 IP 每秒最多 POST 多少个请求。Go 程序中使用的方法:package main import (     "github.com/didip/tollbooth"     "net/http"     "time" ) func HelloHandler(w http.ResponseWriter, req *http.Request) {     w.Write([]byte("Hello, World!")) } func main() {     // You can create a generic limiter for all your handlers     // or one for each handler. Your choice.     // This limiter basically says: allow at most 1 request per 1 second.     limiter := tollbooth.NewLimiter(1, time.Second)     // This is an example on how to limit only GET and POST requests.     limiter.Methods = []string{"GET", "POST"}     // You can also limit by specific request headers, containing certain values.     // Typically, you prefetched these values from the database.     limiter.Headers = make(map[string][]string)     limiter.Headers["X-Access-Token"] = []string{"abc123", "xyz098"}     // And finally, you can limit access based on basic auth usernames.     // Typically, you prefetched these values from the database as well.     limiter.BasicAuthUsers = []string{"bob", "joe", "didip"}     // Example on how to wrap your request handler.     http.Handle("/", tollbooth.LimitFuncHandler(limiter, HelloHandler))     http.ListenAndServe(":12345", nil) 标签:Tollbooth
你可以使用OkHttp库来进行POST请求,将本地图片上传到服务器。下面是一个示例代码: ```java // 引入OkHttp库 import okhttp3.*; import java.io.File; import java.io.IOException; public class ImageUploader { public static void main(String[] args) { // 创建OkHttpClient客户端 OkHttpClient client = new OkHttpClient(); // 创建要上传的文件 File file = new File("path/to/your/image.jpg"); // 创建请求体 RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("image", file.getName(), RequestBody.create(MediaType.parse("image/jpeg"), file)) .build(); // 创建POST请求 Request request = new Request.Builder() .url("http://example.com/upload") // 替换为实际的上传地址 .post(requestBody) .build(); // 发送请求并处理响应 try { Response response = client.newCall(request).execute(); if (response.isSuccessful()) { System.out.println("上传成功!"); } else { System.out.println("上传失败:" + response.message()); } } catch (IOException e) { e.printStackTrace(); } } } ``` 需要注意的是,你需要将`"path/to/your/image.jpg"`替换为你本地图片的实际路径,将`"http://example.com/upload"`替换为实际的上传地址。 这段代码会将指定的图片文件作为表单数据的一部分,通过POST请求发送到服务器。服务器端需要相应的接口来接收并处理这个请求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值