You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效使用WebView的evaluateJavaScript方法传输文件?

优化Android WebView加载PDF的方案

你的核心问题在于通过evaluateJavascript传递完整字节数组——这种方式会将每个字节序列化为JSON元素,不仅内存开销极大,还会阻塞跨进程通信,直接导致大文件加载失败。下面是两种更优的解决方案:

方案一:直接启用WebView原生文件输入功能

让WebView自带的文件输入控件处理选择逻辑,完全跳过Android层的字节数组中转,是最简单高效的方案。

步骤1:配置WebView允许文件访问

在初始化WebView时添加以下设置:

val webSettings = myWebView.settings
webSettings.javaScriptEnabled = true
webSettings.allowFileAccess = true
webSettings.allowContentAccess = true
webSettings.domStorageEnabled = true

步骤2:前端使用原生文件输入控件

在你的HTML页面中添加标准文件选择按钮:

<input type="file" accept="application/pdf" id="pdfInput">
<script>
document.getElementById('pdfInput').addEventListener('change', (e) => {
  const file = e.target.files[0];
  if (!file) return;
  
  const fileReader = new FileReader();
  fileReader.onload = function() {
    renderPdf(new Uint8Array(this.result));
  };
  fileReader.readAsArrayBuffer(file);
});
</script>

这种方式下,用户点击文件选择按钮后,WebView会自动调用系统文件选择器,选中文件后JS直接获取File对象,无需Android层介入,完全避免字节数组传递的性能问题。

方案二:传递Content URI给JS直接读取

如果需要在Android层先对文件做预处理(比如验证、日志),可以传递文件的Content URI给JS,让JS通过网络请求方式读取文件内容,而非传递完整字节数组。

步骤1:修改Android代码传递URI并授予权限

修改你的resultLauncher逻辑,不再读取字节数组,而是传递URI并授予WebView持久访问权限:

private var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    if (result.resultCode == RESULT_OK) {
        result?.data?.also { intent ->
            val uri = intent.data ?: return@also
            // 授予WebView持久读取权限
            contentResolver.takePersistableUriPermission(
                uri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION
            )
            // 传递URI给JS
            myWebView.evaluateJavascript("renderPdfByUri('${uri.toString()}')", null)
        }
    }
}

步骤2:JS通过URI读取文件内容

修改JS方法,通过fetch读取URI对应的文件:

function renderPdfByUri(uri) {
    fetch(uri)
        .then(response => response.arrayBuffer())
        .then(buffer => {
            renderPdf(new Uint8Array(buffer));
        })
        .catch(error => console.error('加载PDF失败:', error));
}

这种方式仅传递一个字符串URI,内存开销可以忽略,且支持任意大小的PDF文件,同时保留了Android层对文件选择的控制能力。

方案对比

  • 方案一:无需修改Android层业务逻辑,完全依赖WebView原生能力,开发成本最低,适合无特殊预处理需求的场景。
  • 方案二:保留Android层对文件的控制权,适合需要先验证文件、记录日志等前置操作的场景,性能同样优异。

内容的提问来源于stack exchange,提问作者Eboy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 21:29:59