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
相关产品推荐
相关产品推荐

