Flutter Web下载按钮异常:下载文件为HTML而非PDF求助
解决Flutter Web下载文件得到HTML而非目标文件的问题
问题根源
浏览器存在安全限制,无法直接访问本地文件系统的绝对路径(比如你代码里的/Users/aaa/Desktop/a.pdf)。当你直接把这个路径传给AnchorElement时,浏览器会将其解析为当前网页的相对URL去请求服务器,而服务器找不到该资源,就会返回404错误页面的HTML,这就是你下载到非预期文件的原因。
解决方案
根据你的需求场景,分两种情况处理:
场景1:让用户选择本地文件并下载
通过浏览器的文件选择器让用户手动选择文件,再读取文件内容生成可下载的Blob:
ElevatedButton( onPressed: () async { // 创建文件选择输入框 final fileInput = FileUploadInputElement()..accept = '.pdf'; fileInput.click(); // 等待用户选择文件 await fileInput.onChange.first; if (fileInput.files?.isNotEmpty == true) { final selectedFile = fileInput.files!.first; _downloadFile(selectedFile, 'jjjjjj.pdf'); } }, child: const Text('Download PDF'), ),
对应的下载函数:
void _downloadFile(File file, String fileName) { // 生成Blob的临时URL final fileUrl = Url.createObjectUrlFromBlob(file); final anchor = AnchorElement(href: fileUrl) ..download = fileName ..target = '_blank'; anchor.click(); // 释放临时URL资源 Url.revokeObjectUrl(fileUrl); }
场景2:下载Flutter项目中的资源文件(如assets目录下的PDF)
如果要下载的是项目内置的资源文件,先通过rootBundle加载资源字节数据,再转为Blob:
- 先在
pubspec.yaml中配置资源:
flutter: assets: - assets/a.pdf
- 实现下载逻辑:
ElevatedButton( onPressed: () async { // 加载assets中的PDF文件 final assetData = await rootBundle.load('assets/a.pdf'); final pdfBytes = assetData.buffer.asUint8List(); // 创建PDF类型的Blob final pdfBlob = Blob([pdfBytes], 'application/pdf'); _downloadFile(pdfBlob, 'jjjjjj.pdf'); }, child: const Text('Download Asset PDF'), ),
对应的下载函数:
void _downloadFile(Blob blob, String fileName) { final fileUrl = Url.createObjectUrlFromBlob(blob); final anchor = AnchorElement(href: fileUrl) ..download = fileName ..target = '_blank'; anchor.click(); Url.revokeObjectUrl(fileUrl); }
关键注意事项
- 浏览器不允许直接访问本地文件系统路径,必须通过用户交互(如文件选择器)或加载项目资源的方式获取文件内容。
- 使用
Url.createObjectUrlFromBlob生成临时URL后,记得调用Url.revokeObjectUrl释放资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Romeo Velloni
相关产品推荐
相关产品推荐

