junny_previewer 0.2.0
junny_previewer: ^0.2.0 copied to clipboard
Flutter inline WebView file preview package backed by a replaceable File Viewer web bundle.
junny_previewer #
独立的 Flutter inline WebView 文件预览依赖,负责承载 File Viewer Web 构建产物,并把 Flutter/Dart 文件来源转换为受限的 JavaScript bridge 协议。上层 Flutter package 可以基于它封装自己的文件预览入口,而不需要让调用方直接处理 WebView 或 npm 资源。
安装 #
0.2.0 配套核心与三档资源使用协议版本 1,要求 Dart 3.12 / Flutter 3.44。它与 0.1.x 的资源组合不兼容,正式发布后由 Pub 依赖约束保证组合;以下本地 overrides 仅用于未发布源码联调。
宿主必须同时依赖主包和一个资源档位,下面以 office 档位为例:
dependencies:
junny_previewer: ^0.2.0
junny_previewer_assets_office: ^0.2.0
lite、office 和 full 资源包必须选择其中一个,不能同时依赖多个档位。
当前能力 #
仓库当前包含可运行的 WebView、来源抽象、分块传输协议、三档资源包和 File Viewer v2.2.5 的真实构建产物。当前资源目录解压体积约为 lite 6 MB、office 53 MB、full 201 MB;资源构建脚本会把对应产物复制到独立 asset package。
API 示例 #
import 'dart:typed_data';
import 'package:junny_previewer/junny_previewer.dart';
import 'package:junny_previewer_assets_office/junny_previewer_assets_office.dart';
JunnyFileViewer(
config: const JunnyPreviewerConfig(
assetBundle: junnyPreviewerOfficeAssets,
),
source: FilePreviewSource.bytes(
Uint8List.fromList(fileBytes),
fileName: 'contract.docx',
),
onDownloadRequested: (JunnyPreviewerFile file) async {
// 由宿主决定保存目录、系统分享或业务下载记录。
},
)
PDF 的打印按钮会通过 WebView bridge 回到 Dart,并由包内 printing 调用系统打印面板;
下载按钮同样回到 onDownloadRequested,不会使用 WebView 的浏览器下载行为。Office 文件仍可预览,
但原生打印回调只对 PDF 开放,Office 文件如需打印应由宿主先转换为 PDF。
URI 适合 WebView 能直接访问且无需额外鉴权的文件;带 Cookie、OSS headers 或 Dio 登录态的文件应在 Dart 侧读取为 bytes/stream。文件名必须保留正确扩展名,File Viewer 依赖它选择 renderer。
资源档位和真实减包 #
packages/junny_previewer_assets_lite:轻量文本/图片等基础能力。packages/junny_previewer_assets_office:PDF、Word、Excel、PowerPoint 等办公文件。packages/junny_previewer_assets_full:完整发布包,包含全部 renderer;体积显著更大。
Flutter 会无条件打包一个依赖 package 在 pubspec 中声明的全部 assets,因此单纯运行时 enum 不能减包。本项目把资源拆为三个独立 asset package;宿主只依赖其中一个,并把该 package 导出的 JunnyPreviewerAssetBundle 传给配置,最终安装包才只包含一个档位。真实构建资源应固定版本并执行许可证扫描;第三方 renderer 的许可证不应笼统视为 Apache-2.0。
构建真实 File Viewer 资源 #
在独立的 Node 构建目录安装匹配版本的 File Viewer package,按官方文档生成完整静态资源,例如 @file-viewer/web-full 的 dist 或 file-viewer-copy-assets 输出。将最终 index.html、renderer chunks、Worker、WASM、字体和 vendor 文件放入对应 asset package 的 assets/file_viewer/,然后运行 flutter pub get 和应用构建。
不要只复制入口 IIFE;缺少 Worker/WASM/字体时,轻量格式可能正常但 Office/PDF/重型格式会失败。
安全与平台边界 #
Android/iOS 使用 webview_flutter;Web 使用同一资源包的 iframe 和消息桥接。bridge 不提供任意 JavaScript 执行接口,URI 受 allowedOrigins 限制,文件大小受 maxFileBytes 限制,二进制请求使用固定版本和 offset/size 校验。真实 PDF 已在 Android WebView 和 iOS WKWebView 模拟器通过正文渲染 smoke;Office 全格式、超大文件和业务 fallback 仍需使用业务样本继续验证。
资源服务使用 localhost loopback HTTP,以保证 Android/iOS WebView 中的 ES module、Worker 和 WASM 同源加载。Android release 宿主应通过 networkSecurityConfig 仅允许 localhost/127.0.0.1 的 cleartext,不要全局打开明文流量;iOS release 宿主应按应用安全策略允许本机网络。debug/dev 宿主可以临时放宽该策略,但不能直接复制到生产配置。
Web 行为与部署 #
Web 加载 assetBundle.viewerAssetKey 对应的 Flutter asset,不直接把附件 URL 作为 iframe 页面。宿主应保留完整资源目录,部署到子路径时配置正确的 <base href>。URI 下载受浏览器 CORS、HTTPS 混合内容及服务端鉴权限制;有自定义 headers 或需要 HTTP 重定向的文件由宿主下载后传入 bytes/stream,预览器不自动跟随跳转以避免绕过来源限制。
本地联调必须同时覆盖预览器和实际使用的资源包,否则 Dart 可能等待旧版资源不支持的 Web 握手。例如宿主与本仓库位于同级目录、使用 full 档位时:
dependency_overrides:
junny_previewer:
path: ../junny_previewer
junny_previewer_assets_full:
path: ../junny_previewer/packages/junny_previewer_assets_full
执行 flutter pub get 后确认宿主 .dart_tool/package_config.json 的两个路径均指向本地。切换 lite/office 档位时对应覆盖所选资源包。新增 pointer_interceptor 等插件后必须停止并重新执行 flutter run,仅热重启可能仍保留旧的 Web 插件注册代码,导致悬浮下载按钮的点击穿透到 iframe。
切换 source 会取消旧请求,只有 renderer 报告完成后才触发 onReady。握手缺失或协议版本不匹配会立即触发 bridge_version_mismatch;完全不回握手的旧资源在 60 秒后超时。文件读取失败、超限、长度不匹配或 60 秒内未完成预览会触发 onError,界面提供本地化的重试入口。Web 下载按钮将当前文件字节交给 onDownloadRequested。HTML 附件在禁止脚本和同源访问的子框架中显示。
浏览器回归测试:
flutter test --platform chrome
# 另需安装 Playwright 和本机 Chrome;也可用 JUNNY_PLAYWRIGHT_MODULE 指定现有模块路径。
node test/browser_bridge_smoke.mjs
Dart 浏览器测试覆盖状态、切换、取消和下载;Node smoke 使用实际生成的 lite/office/full 资源验证文本、HTML、DOCX、XLSX 渲染。测试样例位于 test/fixtures/。
体积测量 #
当前 v2.2.5 构建实测:lite 约 6 MB,office 约 53 MB(包含约 16 MB 的 PPT CJK 字体),full 约 201 MB。分别统计每个档位目录的解压大小,再比较宿主应用的 release 构建产物;不能用 npm tarball 大小代替 APK/IPA 增量。
开发与发布检查 #
flutter pub get
dart analyze .
flutter test
示例工程测试在 example 目录执行:
flutter test
Web 资源只在升级 File Viewer 或调整 bridge 时重新构建,具体命令见 web/README.md。版本变化同步记录在 CHANGELOG.md;首版提交、v0.1.0 标签和推送由发布人确认后执行。