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

Android Studio中WebView通过JavaScript访问项目外部文件问题

解决Android WebView中JS fetch访问非assets目录文件的问题

方案一:利用res/raw目录存储文件(适合不希望放assets的情况)

res/raw目录可存放任意类型文件,且不会被编译压缩,步骤如下:

  1. 放置文件:将目标文件放入res/raw目录(无则新建),文件名仅支持小写字母、数字、下划线。
  2. Android端暴露文件读取接口:
    创建供JS调用的接口类,通过addJavascriptInterface绑定到WebView:
    public class RawFileReader {
        private Context context;
    
        public RawFileReader(Context ctx) {
            context = ctx;
        }
    
        @JavascriptInterface
        public String readRawFile(String fileName) {
            int resId = context.getResources().getIdentifier(fileName, "raw", context.getPackageName());
            if (resId == 0) return null;
    
            try (InputStream is = context.getResources().openRawResource(resId);
                 BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
                StringBuilder content = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    content.append(line).append("\n");
                }
                return content.toString();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    
        // 读取二进制文件(返回Base64字符串)
        @JavascriptInterface
        public String readRawBinaryFile(String fileName) {
            int resId = context.getResources().getIdentifier(fileName, "raw", context.getPackageName());
            if (resId == 0) return null;
    
            try (InputStream is = context.getResources().openRawResource(resId)) {
                byte[] bytes = new byte[is.available()];
                is.read(bytes);
                return Base64.encodeToString(bytes, Base64.DEFAULT);
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    
    在WebView初始化时绑定接口:
    webView.addJavascriptInterface(new RawFileReader(this), "RawFileReader");
    webView.getSettings().setJavaScriptEnabled(true);
    
  3. JS中调用接口获取文件:
    // 读取文本文件(如res/raw/data.txt)
    const textContent = await window.RawFileReader.readRawFile("data");
    // 读取二进制文件并转成Blob
    const base64Data = await window.RawFileReader.readRawBinaryFile("image");
    const blob = await fetch(`data:image/png;base64,${base64Data}`).then(res => res.blob());
    

方案二:使用assets子目录分类存储(最简单的方法)

assets目录支持所有文件类型,可通过创建子目录避免杂乱(如assets/files/、assets/media/),直接用file:///android_asset/路径访问:

// 访问assets/files/data.csv
fetch('file:///android_asset/files/data.csv')
  .then(res => res.text())
  .then(content => {
      // 处理文件内容
  });

// 访问assets/media/image.png
fetch('file:///android_asset/media/image.png')
  .then(res => res.blob())
  .then(blob => {
      // 处理二进制文件
  });

确保WebView开启文件访问权限:

webView.getSettings().setAllowFileAccess(true);

方案三:复制文件到内部存储后用file://路径访问

适合需要修改文件或频繁读取的场景:

  1. 首次启动复制文件:将APK内的文件(来自assets/raw)复制到应用内部存储:
    private void copyToInternalStorage(String srcAssetPath, String destFileName) {
        File destFile = new File(getFilesDir(), destFileName);
        if (destFile.exists()) return;
    
        try (InputStream is = getAssets().open(srcAssetPath);
             OutputStream os = new FileOutputStream(destFile)) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
  2. 传递路径给JS:
    String fileUrl = "file://" + new File(getFilesDir(), "data.txt").getAbsolutePath();
    webView.loadUrl("javascript:window.localFileUrl = '" + fileUrl + "';");
    
  3. JS中fetch访问:
    fetch(window.localFileUrl)
      .then(res => res.text())
      .then(content => {
          // 处理内容
      });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 11:15:59