如何解决Android WebView下载网页Excel文件为空的问题
问题根因
WebView下载得到空Excel文件,和以下几个常见实现缺陷直接相关:
- 站点Excel导出接口存在请求校验,现有代码仅传递Cookie和UA,缺少Referer等必填头,或接口要求POST请求但DownloadManager默认发GET请求,服务端返回空响应/错误跳转页,保存为.xlsx后缀后自然显示为空
- 存储配置未适配Android 10+分区存储规则,旧版WRITE_EXTERNAL_STORAGE权限在高版本失效,路径写入异常生成空文件
- 硬编码回调返回的mimeType,当服务端返回的响应头mimeType和实际文件不匹配时,会触发DownloadManager请求拦截,拿到空内容
修复步骤
1. 修正清单文件配置
替换原有存储权限配置,适配全版本Android系统:
<!-- Android 13+ 通知权限,用于显示下载进度 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Android 13+ 媒体文件读取权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- Android 9及以下版本存储写入权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" /> <application ... android:requestLegacyExternalStorage="true" ...>
2. 替换下载监听逻辑
补全必要请求头,移除错误的mimeType硬编码,适配高版本存储规则:
// 权限申请逻辑同步调整:Android 13+申请POST_NOTIFICATIONS,Android 9及以下才申请WRITE_EXTERNAL_STORAGE if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_DENIED) { requestPermissions(new String[]{Manifest.permission.POST_NOTIFICATIONS}, 1); } } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) { requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } } // 下载监听逻辑 web_view.setDownloadListener((url, userAgent, contentDisposition, mimeType, contentLength) -> { String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType); String cookies = CookieManager.getInstance().getCookie(url); DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); // 移除原有的setMimeType调用,让DownloadManager自动从响应头识别文件类型,避免拦截 // 补全Referer请求头,绝大多数站点会校验该字段防止非法跨域请求 request.addRequestHeader("cookie", cookies); request.addRequestHeader("User-Agent", userAgent); request.addRequestHeader("Referer", web_view.getUrl()); request.setDescription("下载中"); request.setTitle(fileName); request.allowScanningByMediaScanner(); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); request.setAllowedOverMetered(true); request.setAllowedOverRoaming(true); request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName); DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); dm.enqueue(request); Toast.makeText(getApplicationContext(), "文件已开始下载,可在通知栏查看进度,完成后在系统下载目录查找", Toast.LENGTH_LONG).show(); });
3. POST导出场景特殊处理
如果页面Excel导出是通过表单POST提交触发的,DownloadManager默认发GET请求无法拿到内容,需要在WebView初始化时开启以下配置,让WebView自动处理POST类下载请求:
web_view.getSettings().setJavaScriptEnabled(true); web_view.getSettings().setDomStorageEnabled(true); web_view.getSettings().setAllowFileAccess(true); CookieManager.getInstance().setAcceptThirdPartyCookies(web_view, true);
排查技巧
- 若下载得到的文件大小仅几KB,可将后缀改为.txt打开查看内容,大概率是服务端返回的鉴权失败、参数错误提示页,说明请求头或请求方法不匹配
- 对比Chrome浏览器触发下载时的请求方法、请求头参数,和WebView发出的请求对齐即可解决90%以上的空文件问题
- Android 10及以上版本不要申请WRITE_EXTERNAL_STORAGE权限,该权限在高版本已失效,强制申请反而会导致存储访问异常
内容的提问来源于stack exchange,提问作者Computer knowledge
相关产品推荐
相关产品推荐

