首页/新闻资讯/正文详情

dio_web_adapter 实战指南:让 Dio 在 Web 与 WASM 上无缝运行

发布时间:2026/9/23 2:47:09 来源:云帆数科 栏目:资讯中心
dio_web_adapter 实战指南:让 Dio 在 Web 与 WASM 上无缝运行
dio_web_adapter 实战指南让 Dio 在 Web 与 WASM 上无缝运行【免费下载链接】dioA powerful HTTP client for Dart and Flutter, which supports global settings, Interceptors, FormData, aborting and canceling a request, files uploading and downloading, requests timeout, custom adapters, etc.项目地址: https://gitcode.com/gh_mirrors/di/dioDio 是 Dart / Flutter 生态中流行的 HTTP 客户端而dio_web_adapter仓库位于 plugins/web_adapter为 Dio 提供了 Web 平台专用适配器使基于 XHR 的网络请求、文件下载、进度回调与超时控制能够在浏览器中正常工作。读完本文你将掌握如何安装与启用该适配器、理解其核心参数withCredentials、enableCORSWarning的语义、弄清 Web 端文件下载的限制与正确用法并从源码层面理解 CORS 预检、超时判定与取消机制是如何实现的。一、包定位Web 平台能力的默认实现dio_web_adapter的核心定位是把 Dio 在 Web 平台的底层 HTTP 能力从主包中拆分出来独立成包。它通过实现 Dio 的 HttpClientAdapter 接口让同一套 Dio API 在浏览器中正常工作。事实依据该包的 1.0.0 版本变更日志CHANGELOG.md明确记录“Split the Web ability from thepackage:dio”即“将 Web 能力从 package:dio 中拆分”。从包的导出结构看lib/dio_web_adapter.dart它主要导出五部分实现adapter_impl.dartBrowserHttpClientAdapter核心的 HTTP 适配器基于 XMLHttpRequestdio_impl.dartDioForBrowser为 Web 定制的Dio实例覆盖了download等平台相关行为compute_impl.dartWeb 端的compute实现对应 Flutter foundation 的_isolates_web.dartmultipart_file_impl.dartWeb 端不支持MultipartFile.fromPath直接抛出UnsupportedErrorprogress_stream_impl.dart对请求流的进度包装支持取消检查。其中adapter.dart已被标记为Deprecated提示改为导入adapter_impl.dart这是为了避免与package:web等产生命名冲突见 CHANGELOG 2.1.1。二、版本兼容性与安装版本兼容矩阵该适配器与 Dart / Flutter 的兼容关系如下摘自 README.md版本Dart最低Flutter最低1.x2.18.03.3.02.x3.3.03.19.0注意实际可解析到的版本由你使用的 SDK 决定。运行dart pub upgrade或flutter pub upgrade可获取当前 SDK 下最新的可解析版本。2.x 系列之所以要求更高 SDK是因为其引入了 WASMWebAssembly编译目标支持见 CHANGELOG.md 2.0.0。安装步骤虽然包名为dio_web_adapter但它已经被内嵌进package:dio主包正常情况下你无需显式安装直接用dio即可在 Web 端获得浏览器适配器。只有当你有特殊诉求时才需要把dio_web_adapter显式加入 pubspec 依赖dependencies: dio: ^5.8.0 dio_web_adapter: ^2.2.1该包自身的依赖很轻dio、http_parser、meta以及webDart 官方的浏览器互操作库见 pubspec.yaml这也是它能同时支持 JS 与 WASM 编译目标的关键。三、快速上手一分钟跑通 Web 请求官方示例README.md给出了一段最小可用代码import package:dio/dio.dart; // 该导入并非必需甚至可能触发 lint 提示。 // import package:dio_web_adapter/dio_web_adapter.dart; void main() async { final dio Dio(); dio.httpClientAdapter BrowserHttpClientAdapter(withCredentials: true); // 发起请求。 final response await dio.get(https://dart.dev); print(response); }两个关键点无需显式导入默认的Dio()在 Web 平台会自动使用BrowserHttpClientAdapter。显式导入dio_web_adapter只在你需要直接引用适配器类型比如自定义构造参数时才需要。入口选择如果希望显式使用浏览器实现可以像 test/browser_test.dart 那样import package:dio/browser.dart;该入口提供DioForBrowserexample/main.dart 还演示了配合LogInterceptor的使用方式。核心构造参数BrowserHttpClientAdapter的构造函数源码见 lib/src/adapter_impl.dart只有两个参数参数默认值含义withCredentialsfalse跨域请求是否携带凭据如 Cookie、Authorization 头enableCORSWarningtrue当请求不是 CORS “简单请求”、会触发预检OPTIONS时是否打印告警日志withCredentials的逐请求覆盖除了在构造时全局设置你还可以通过Options.extra[withCredentials]为单个请求覆盖该值源码 adapter_impl.dartdio.get( https://api.example.com/me, options: Options(extra: {withCredentials: true}), );enableCORSWarning的语义置为false可以关闭“非简单请求”的每请求告警日志但即便关闭DioException.connectionError中经过 CORS 信息增强的错误原因仍然会输出见 CHANGELOG.md 2.2.1 与 adapter_impl.dart。四、Web 端文件下载Dio.download的完整说明从 2.2.0 起Dio.download在 Web 平台得到支持。其实现位于 lib/src/dio_impl.dart流程是先用 Dio 以字节形式ResponseType.bytes请求完整响应再通过 Blob URL 触发浏览器下载。savePath 的真实语义在 Web 端savePath不是本地文件系统路径而是“建议文件名”。实际保存位置由浏览器决定。_suggestedFilenameFromPathdio_impl.dart会做三件事把反斜杠\归一化为/截取最后一个/之后的部分作为文件名若结果为空回退为download。因此以下调用会建议浏览器以report.pdf为名保存文件await dio.download(https://example.com/report, downloads/report.pdf);返回 Response 不等于写入成功一个容易误解的点download返回的Response仅代表Dio 已经获取到响应字节并派发了浏览器下载动作click它不保证浏览器真的写盘、保留你建议的文件名或跳过用户确认弹窗。是否写盘、是否改名、是否弹窗完全由浏览器、用户设置与页面安全策略控制。平台限制清单务必逐条对照Web 端下载存在以下硬性限制摘自 README.md 的 Downloading files 一节CORS 依然生效请求仍然经由 Dio 发起因此受 CORS 约束协议由浏览器决定网络请求通过 XHR 由浏览器处理HTTP/1.1、HTTP/2、HTTP/3 等协议细节均由浏览器控制整响应先入内存浏览器开始下载前完整响应体已经加载进内存不适合超大文件流式下载依赖标准浏览器 API触发下载依赖浏览器对Blob、URL.createObjectURL与HTMLAnchorElement.download的标准支持FileAccessMode.append不支持会直接抛出UnsupportedError见 dio_impl.dartdeleteOnError无实际作用Web 端没有本地文件可删除自定义lengthHeader不生效进度总大小来自浏览器响应进度事件progress event而非 Content-Length 头。底层下载触发器的实现下载触发逻辑在 lib/src/download_trigger.dart 中通过可注入的函数createObjectUrl、createDownloadAnchor、clickDownloadAnchor等均标注visibleForTesting实现便于浏览器端测试替换。核心_triggerBrowserDownload流程将响应字节转为 JS 类型化数组构造web.Blob可选传入 Content-Type用web.URL.createObjectURL生成blob:URL创建a downloadfilename hrefblob:...并挂载到document.body后再点击部分浏览器对脱离文档的节点更严格在finally中移除锚点并调用revokeObjectURL释放 URL。其中特意改用package:web与dart:js_interop而不是旧的dart:html以保证该路径在 Dart 的 WASM 编译目标下依然可用见 download_trigger.dart 的注释。五、源码深读BrowserHttpClientAdapter 的请求生命周期BrowserHttpClientAdapter.fetchlib/src/adapter_impl.dart是 Web 请求的完整实现下面拆解其关键阶段。1. 建立 XHR 并配置凭据与请求头final xhr web.XMLHttpRequest(); xhrs.add(xhr); xhr ..open(options.method, ${options.uri}) ..responseType arraybuffer;响应类型固定为arraybuffer保证能拿到原始字节withCredentials优先取options.extra[withCredentials]未设置时才回退到构造参数Content-Length头会被移除浏览器不允许手动设置其他请求头通过setRequestHeader写入Iterable值会以,拼接。2. 超时计时connect receive 合并为 XHR timeoutfinal xhrTimeout (connectTimeout receiveTimeout).inMilliseconds; xhr.timeout xhrTimeout;连接超时通过独立的Timer实现只有xhr.readyState HEADERS_RECEIVED即尚未收到响应头时才判定为连接超时收到响应头后的等待交给“接收超时”处理adapter_impl.dart。这样避免了一个请求已完成却仍触发超时的误判。接收超时采用“每次收到进度事件就重置计时器”的滑动窗口策略watchReceiveTimeout在每个 progress 事件到来时重置receiveStopwatch超时后调用xhr.abort()并抛出DioException.receiveTimeoutadapter_impl.dart。3. 发送进度与上传监听器的“副作用”源码中有段注释非常关键adapter_impl.dart只有绝对必要时才注册xhr.upload的 progress 监听器因为一旦注册上传监听器该请求就不再属于 CORS “简单请求”会强制触发预检。具体逻辑仅当requestStream ! null且设置了sendTimeout或onSendProgress时才会注册上传监听器sendTimeout用Stopwatch记录“有数据上传的耗时”超过阈值则抛DioException.sendTimeout若没有请求体却设置了sendTimeout/onSendProgress会输出告警日志因为它们根本无法生效。4. 取消与关闭传入的cancelFuture一旦完成会调用xhr.abort()并抛出DioException.requestCancelledadapter_impl.dartclose(force: true)会 abort 所有活跃的 XHRclose()默认清空追踪集合adapter_impl.dart每个活跃 XHR 被记录在xhrs集合中标注visibleForTesting供测试断言如 test/browser_test.dart 验证withCredentials是否正确传递。5. 错误映射XHR 的onError回调无法提供具体错误信息浏览器 API 限制因此适配器统一抛出DioException.connectionError并附上 CORS 增强说明见下文。XHR 自身的timeout事件则依据readyState区分连接超时与接收超时。六、CORS 预检的智能告警与错误增强跨域请求在浏览器中最大的坑是 CORS 预检。该适配器 2.2.1 起内置了一套“预检原因分析”机制实现集中在 lib/src/cors.dart且全部是纯函数便于脱离浏览器做单元测试。“简单请求”判定标准corsPreflightReason(RequestOptions)会按以下顺序检查任何一条不满足都会返回触发预检的原因方法必须是 CORS 白名单方法GET/HEAD/POSTContent-Type必须是白名单值application/x-www-form-urlencoded、multipart/form-data、text/plain含;charset...等参数时会先截取 MIME 部分再比较请求头必须全部在安全名单内accept、accept-language、content-language、content-type、range。运行时叠加因素collectCorsPreflightReasons在静态分析之外还会叠加两个运行时因素注册了上传进度监听器sendTimeout或onSendProgress存在withCredentials被启用凭据请求一律需要预检。告警与错误增强当检测到预检原因且enableCORSWarning true时适配器会打印告警日志明确指出该请求会触发 OPTIONS 预检若服务器不处理预检则请求必然失败。同时corsEnrichedErrorReason会把预检原因拼进DioException.connectionError的reason中提示开发者检查服务器是否正确响应 CORS 预检——这一增强不管enableCORSWarning如何设置都会输出。实战建议当你发现 Web 请求报DioException.connectionError且附带 “not a CORS simple request” 类说明时优先排查服务器对 OPTIONS 预检的处理而不是怀疑 Dio 本身。七、Web 端的其他实现细节computeWeb 上不存在真正的并发compute_impl.dart对应 Flutter foundation 的_isolates_web.dartWeb 平台没有 isolate因此实现为await null后同步执行回调避免昂贵的计算立即阻塞 UI 帧compute_impl.dart。它本质上只是把执行推迟到下一帧。进度流取消检查的注入点progress_stream_impl.dart的addProgress在数据流中逐块检查options.cancelToken若已取消则把cancelToken.cancelError注入流错误并关闭流progress_stream_impl.dart。MultipartFile文件路径 API 在 Web 不可用multipart_file_impl.dart中MultipartFile.fromPath/fromPathSync直接抛出UnsupportedError提示“MultipartFile 仅在可用 dart:io 的平台受支持”。Web 端应改用字节内容构造MultipartFile.fromBytes浏览器没有本地文件路径概念。八、测试与验证仓库为该适配器配备了浏览器环境测试运行方式遵循 Dart 标准测试约定dart_test.yaml见 plugins/web_adapter/dart_test.yaml。现有用例包括browser_test.dart以TestOn(browser)标注验证withCredentials是否正确透传到 XHRcors_preflight_test.dart对cors.dart的纯函数做单元测试download_test.dart利用download_trigger.dart中可注入的测试钩子验证下载触发逻辑。如果你在使用中遇到问题仓库 README 的呼吁同样适用于你与其坐等修复不如提交一个失败的测试用例failing test case或直接提 PR。总结dio_web_adapter是 Dio 在 Web 与 WASM 平台的“心脏”BrowserHttpClientAdapter基于 XHR 提供请求、超时、进度、取消与 CORS 告警DioForBrowser提供了贴合浏览器语义的download实现compute与progress_stream则补齐了平台差异。理解“savePath 只是建议文件名”“返回 Response 不代表写盘成功”“注册上传监听会破坏简单请求判定”这三个关键点就能在 Web 端写出行为可预期、问题可定位的 Dio 代码。【免费下载链接】dioA powerful HTTP client for Dart and Flutter, which supports global settings, Interceptors, FormData, aborting and canceling a request, files uploading and downloading, requests timeout, custom adapters, etc.项目地址: https://gitcode.com/gh_mirrors/di/dio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

3步拆解2018款哈弗h6图解原理,告别语法焦虑
3步拆解2018款哈弗h6图解原理,告别语法焦虑

3步拆解2018款哈弗h6图解原理,告别语法焦虑 很多老铁手里攥着一本《Python编程:从入门到实践》,背下了 for 循环和 if 判断,可一旦要接个真实业务,比如处理一下 2018款哈弗h6… · 2026/9/23 2:47:02

Agent会话内记忆:让AI在连续对话中不“失忆”的工程指南
Agent会话内记忆:让AI在连续对话中不“失忆”的工程指南

你有没有遇到过这种场景:自己写的Agent,单轮问答表现还行,但只要用户开始说“刚才那个结果再解释一下”“把上一段的语气调得正式一点”“我前面说过我不吃辣”,它就完全掉线。不是模型不够聪明,而是你的Agent没有记忆… · 2026/9/23 2:46:56

PHP-CS-Fixer 规则详解:no_whitespace_before_comma_in_array 清理数组逗号前的空白
PHP-CS-Fixer 规则详解:no_whitespace_before_comma_in_array 清理数组逗号前的空白

开发工具代码质量静态分析Lint格式化 【免费下载链接】PHP-CS-Fixer A tool to automatically fix PHP Coding Standards issues 项目地址: https://gitcode.com/gh_mirrors/ph/PHP-CS-Fixer 点击查看 免费下载 本篇指南围绕 PHP-CS-Fixer 中数组符号(A… · 2026/9/23 2:46:56

PowerSploit Recon 模块 Get-DomainDFSShare 深度解析:枚举域内分布式文件系统共享
PowerSploit Recon 模块 Get-DomainDFSShare 深度解析:枚举域内分布式文件系统共享

PowerSploit Recon 模块 Get-DomainDFSShare 深度解析:枚举域内分布式文件系统共享 【免费下载链接】PowerSploit PowerSploit - A PowerShell Post-Exploitation Framework 项目地址: https://gitcode.com/gh_mirrors/po/PowerSploit 导读 Get-DomainDFSSh… · 2026/9/23 3:35:02

YOLO遥感油罐检测数据集全解析:标签格式转换与训练避坑指南
YOLO遥感油罐检测数据集全解析:标签格式转换与训练避坑指南

简介:面向YOLO目标检测学习者与遥感图像分析人员,这份遥感油罐检测数据集来自真实场景,图片质量高、场景丰富,使用LabelImg标注且框体质量高,可直接用于YOLOv5、YOLOv8等主流目标检测模型的训练与算法效果验证。压缩包… · 2026/9/23 3:35:02

3步搞定ngg入门到精通:告别报错一脸懵
3步搞定ngg入门到精通:告别报错一脸懵

3步搞定ngg入门到精通:告别报错一脸懵 凌晨三点,屏幕上的红色报错代码像鬼影一样在跳动。你盯着那个 StackTrace ,感觉脑子里一片空白,甚至想直接拔电源。别慌,这种“报错一堆看不懂… · 2026/9/23 3:34:56

Kimi收入20天超全年:K3模型、订阅制与AI应用爆发信号
Kimi收入20天超全年:K3模型、订阅制与AI应用爆发信号

1. 一条出售新闻和一组热词,透露了AI赛道的资金流向信号1.1 沐瞳交易背后的“聚焦主业”逻辑这条新闻刚出来的时候,我身边不少做游戏和做AI的朋友都在转发。字节跳动以60亿美元的价格出售沐瞳科技,这个数字本身就很有话题性。沐瞳科技是《Mob… · 2026/9/23 3:34:56

图解原理搞懂安卓优化,3步解决卡顿,拒绝只会抄代码
图解原理搞懂安卓优化,3步解决卡顿,拒绝只会抄代码

图解原理搞懂安卓优化,3步解决卡顿,拒绝只会抄代码 是不是刷爆了B站和掘金,看了一堆教程还是不会写项目?那些“高斯模糊”、“Shader加速”的视频看得你热血沸腾,一动手写原生Android应用,列表一长就掉帧,点击一下UI卡得像PPT。别… · 2026/9/23 3:34:56

投研领域的Claude Code:Harness如何重构金融工作流
投研领域的Claude Code:Harness如何重构金融工作流

如果你关注AI编程工具,大概率听说过Claude Code这个名字。它让开发者用自然语言直接指挥一个智能体完成从读代码、改代码到跑测试、提PR的完整闭环。那如果把这个思路从代码世界搬到金融市场,会是什么样?李昱琦创办的Panda AI正在做这件事——… · 2026/9/23 3:34:56

3招搞定手机怎么下载微信面试难题实战项目解析
3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧
Win7无线热点配置工具源码解析:解决API失效的3个实战技巧

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧 Win7无线热点配置工具在Win10/11上跑不动?不是你的问题,是版本升级后 API 全变了。很多老项目里的 netsh wlan… · 2026/9/23 0:00:36

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码