bridge.js与原生app大文件通信,上传问题
这个是WebView 与原生层文件传输中大文件内存溢出的典型场景,尤其在移动端(iOS / Android)都很常见。
🧩 场景回顾
-
用户在原生层(Native)选择了文件 F(可能是视频、PDF、音频等,几十 MB~几百 MB)。
-
网页 A(WebView 中加载)要上传这个文件。
-
你有一个 Native ↔ WebView 的 bridge(比如 JSBridge、WKScriptMessageHandler、WebViewJavascriptBridge 等)。
-
问题:不能把整个文件内容通过桥传给 JS,否则内存会爆。
🚫 为什么不能直接传?
因为:
-
JSBridge 通常是通过字符串序列化传递数据(JSON、Base64);
-
Base64 编码会膨胀约 33%,即 100MB 文件 → 133MB 字符串;
-
桥内部复制 + JS 内存开销 + WebView 解析 = 瞬间触发内存压力和崩溃;
-
移动设备上 WebView 内存上限通常不到 200MB。
✅ 常见可行方案(按推荐程度排序)
方案一:原生层负责上传,WebView 只拿结果
🔹最推荐,也是生产中最常见的处理方式
思路:
-
WebView 告诉原生层“我需要上传文件F”;
-
原生层执行真正的上传(比如用
NSURLSessionUploadTask/OkHttp/Retrofit); -
上传完成后把上传进度、**结果(URL、ID)**通过 bridge 通知网页;
-
网页继续执行下一步(比如显示上传成功、调用接口等)。
优点:
-
无内存风险;
-
可后台上传;
-
可断点续传;
-
不受 WebView 限制;
-
通信数据很小(JSON)。
缺点:
-
网页端必须配合,逻辑上不再由 JS 直接发 HTTP。
✅ 推荐在实际项目中这么做。
方案二:原生暴露一个临时 URL / FileHandle 给 WebView
🔹用于网页端直接上传,但文件本体不经过 bridge。
思路:
-
用户选择的文件 F 在原生层保存到临时目录,比如
/tmp/F12345.pdf; -
原生提供一个可访问的本地 URL(例如):
-
Android:通过
FileProvider暴露content://URI; -
iOS:通过
WKURLSchemeHandler或本地 HTTP server 暴露;
-
-
WebView 网页端通过
<input type="file">或fetch(blob)上传; -
实际上传时,WebView 向原生暴露的 URL 读取流数据。
优点:
-
不走桥通道;
-
上传由网页发起;
-
大文件只流式传输。
缺点:
-
实现略复杂;
-
需要小心 URL 安全和生命周期;
-
某些内嵌浏览器(尤其 iOS WKWebView)可能对本地 scheme 访问有限制。