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

Flutter InAppWebView使用loadFile加载本地assets文件带查询参数失效怎么办

Flutter InAppWebView 加载带查询参数的本地assets网页白页解决方案

问题根因

本地资源加载时,Flutter AssetBundle 会把包含?查询参数的完整路径当做实际文件名匹配,找不到对应文件就返回空内容,导致白页;服务端托管时服务端会自动忽略参数匹配静态文件,因此可以正常加载。

解决方案1:请求拦截法(推荐,通用型强)

通过shouldInterceptRequest回调拦截所有webview资源请求,自动剥离参数匹配本地asset资源,同时保留原始查询参数供前端JS读取:

import 'package:flutter/services.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:mime/mime.dart';
import 'dart:convert';

// 页面内InAppWebView配置
InAppWebView(
  initialUrlRequest: URLRequest(
    url: Uri.parse('asset:///assets/board/index.html?letter=5&mode=1'),
  ),
  shouldInterceptRequest: (controller, request) async {
    final requestUrl = request.url!;
    // 剥离查询参数、锚点,获取真实asset路径
    final realPath = requestUrl.origin + requestUrl.path;
    final assetPath = realPath.replaceFirst('asset:///', '');
    
    try {
      // 读取asset资源
      final byteData = await rootBundle.load(assetPath);
      final bytes = byteData.buffer.asUint8List();
      // 获取文件MIME类型
      final mimeType = lookupMimeType(assetPath);
      
      // 如果是html文件,注入查询参数到window对象
      if (mimeType == 'text/html') {
        String htmlContent = utf8.decode(bytes);
        // 注入js把原始查询参数塞到window.location.search
        final injectJs = '''
          <script>
            window.location.search = '${requestUrl.query}';
          </script>
        ''';
        htmlContent = htmlContent.replaceFirst('<head>', '<head>$injectJs');
        return WebResourceResponse(
          contentType: mimeType,
          data: utf8.encode(htmlContent),
          statusCode: 200,
        );
      }
      
      // 其他资源直接返回
      return WebResourceResponse(
        contentType: mimeType,
        data: bytes,
        statusCode: 200,
      );
    } catch (e) {
      // 资源不存在返回404
      return WebResourceResponse(
        statusCode: 404,
      );
    }
  },
)

解决方案2:路径拆分加载法(轻量,适合简单场景)

提前拆分路径和参数,读取html内容后手动注入参数,再用loadData加载:

// 拆分路径和参数
final fullPath = 'assets/board/index.html?letter=5&mode=1';
final pathSegments = fullPath.split('?');
final assetPath = pathSegments.first;
final query = pathSegments.length > 1 ? pathSegments.last : '';

// 读取html内容
final htmlContent = await rootBundle.loadString(assetPath);
// 注入查询参数
final modifiedHtml = htmlContent.replaceFirst('<head>', '''
  <head>
  <script>
    window.location.search = '$query';
  </script>
''');

// 加载html,baseUrl配置为资源所在目录,保证css/js相对路径正常加载
await webViewController.loadData(
  data: modifiedHtml,
  baseUrl: Uri.parse('asset:///assets/board/'),
);

注意事项

  • 提前在pubspec.yaml中声明对应assets目录,确保资源可被访问
  • 若使用mime包判断文件类型,需先在pubspec.yaml中添加mime: ^1.0.5依赖
  • iOS平台无需额外适配,上述两种方案均可兼容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 10:45:09