Android WebView如何将大型二进制ZIP文件传递给Javascript处理
核心问题原因
你fetch失败的根本原因是WebView默认将裸本地路径视为当前站点的相对路径,所以会请求你的Web服务端的对应路径,返回404错误。
问题1:验证文件创建成功并支持JS访问
- 原生侧文件校验:写入完成后调用
file2.exists()判断文件是否存在,调用file2.length()获取文件大小,和原ZIP大小对比,确认文件写入无异常。 - WebView权限配置:初始化WebView时开启本地文件访问权限:
// 允许WebView访问本地文件 webView.getSettings().setAllowFileAccess(true); // 若你的Web应用是远程http/https页面,需开启跨域访问本地文件权限 webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
- 路径格式修正:传给JS的文件路径需要加
file://前缀,即完整路径为file:///storage/emulated/0/Android/data/com.example/files/Download/file2.zip,JS fetch该路径即可正常获取文件内容。
问题2:无需复制文件直接让JS访问原始文件
首先明确:安卓10及以上系统已经限制应用直接获取外部存储文件的真实路径,你找真实路径的思路无法适配全版本系统,不建议继续尝试。
最优解决方案是通过WebView请求拦截实现,步骤如下:
- 原生侧拿到
onActivityResult返回的content URI(即你日志输出的content://com.android.providers.downloads.documents/document/msf%3A12858),直接传给JS使用。 - 重写WebViewClient的
shouldInterceptRequest方法,拦截content协议的请求,直接返回文件输入流给WebView:
@Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { Uri requestUri = request.getUrl(); // 拦截所有content协议的请求 if ("content".equals(requestUri.getScheme())) { try { // 通过ContentResolver打开文件输入流 InputStream inputStream = getContentResolver().openInputStream(requestUri); // 获取文件MIME类型 String mimeType = getContentResolver().getType(requestUri); return new WebResourceResponse(mimeType, "UTF-8", inputStream); } catch (Exception e) { e.printStackTrace(); } } return super.shouldInterceptRequest(view, request); }
该方案完全不需要复制文件,直接复用系统返回的content URI,支持任意大小的文件,也不会有跨域问题,适配所有安卓版本。
内容的提问来源于stack exchange,提问作者Avner Moshkovitz
相关产品推荐
相关产品推荐

