Android加载Google Drive图片时Glide/Picasso返回OkHttp 403错误求助
问题根因
你遇到的随机403错误根本原因不是OkHttp本身的bug,是Google Drive对公开直链的访问限制策略:
- Google Drive会校验请求的
User-Agent、Referer请求头,默认Glide/Picasso自动携带的OkHttp默认UA可能被谷歌判定为异常请求 - 短时间高并发请求相同域名下的资源时,Google会触发临时限流,直接返回403
- 你用Python脚本请求正常是因为脚本里用的UA、请求频率和安卓端OkHttp的请求特征不一样,没有触发谷歌的拦截规则
解决方案
方案1:自定义OkHttp客户端,修改请求头
给Glide/Picasso统一配置自定义的OkHttp实例,请求时主动设置和浏览器一致的UA,清空默认携带的Referer头:
首先自定义拦截器:
import okhttp3.Interceptor; import okhttp3.Response; import java.io.IOException; public class GDriveInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { var request = chain.request().newBuilder() // 设置桌面端Chrome的UA,避免被谷歌拦截 .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36") .removeHeader("Referer") .build(); return chain.proceed(request); } }
给Glide配置自定义OkHttp
首先引入Glide的OkHttp集成依赖,然后自定义GlideModule:
@GlideModule public class CustomGlideModule extends AppGlideModule { @Override public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(new GDriveInterceptor()) // 适当调低并发请求数,避免触发限流 .dispatcher(new Dispatcher(new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<>()))) .build(); registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(okHttpClient)); } }
给Picasso配置自定义OkHttp
OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(new GDriveInterceptor()) .dispatcher(new Dispatcher(new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<>()))) .build(); Picasso picasso = new Picasso.Builder(context) .downloader(new OkHttp3Downloader(okHttpClient)) .build(); Picasso.setSingletonInstance(picasso);
方案2:调整Google Drive链接格式
把你当前的uc?export=download&id=xxx格式的链接替换成Google Drive的缩略图直链格式,稳定性更高:https://lh3.googleusercontent.com/d/你的文件ID=wxxx,末尾的wxxx可以指定图片宽度,比如w1080就是返回宽度1080的适配图片,触发限流的概率比download接口低很多。
方案3:本地缓存优先配置
给Glide/Picasso开启磁盘全缓存,已经加载过的图片不再重复发起网络请求,减少触发限流的概率:
Glide配置示例:
Glide.with(context) .load(url) .diskCacheStrategy(DiskCacheStrategy.ALL) .transition(DrawableTransitionOptions.withCrossFade()) .into(img);
Picasso配置示例:
Picasso.get() .load(url) .networkPolicy(NetworkPolicy.OFFLINE) // 优先读本地缓存 .into(img, new Callback() { @Override public void onSuccess() {} @Override public void onError(Exception e) { // 本地缓存没有再走网络请求 Picasso.get().load(url).into(img); } });
内容的提问来源于stack exchange,提问作者RaulRohjans
相关产品推荐
相关产品推荐

