Android从ASP.NET站点下载文件:DownloadManager功能失效求助
问题排查与解决方案
咱们一步步拆解你遇到的问题,先从最核心的点说起:
1. 核心问题:WebView捕获不到JS触发的下载请求
你的站点下载按钮是通过JavaScript:openAttachment('/doc/28-02-2019.xlsx', 283662);触发的,这种JS调用的下载请求不会触发shouldOverrideUrlLoading方法——这个方法只能拦截直接的URL跳转(比如普通的<a href="真实下载链接">),对JS发起的请求完全无感。
修复方案:用DownloadListener捕获所有下载请求
这是最简单且无需前端配合的方案,WebView自带的setDownloadListener可以捕获任何类型的下载请求,包括JS触发的:
webView.setDownloadListener(new DownloadListener() { @Override public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) { // 1. 构建下载请求 DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); request.setMimeType(mimeType); // 2. 正确解析文件名(替代你原来的错误拼接逻辑) String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType); if (TextUtils.isEmpty(fileName)) { // 兜底方案:用时间戳避免重名 fileName = "Документ_" + System.currentTimeMillis(); } // 3. 配置下载参数 request.allowScanningByMediaScanner(); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); // 4. 适配不同Android版本的存储权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName); } else { // Android 6.0+需要动态申请存储权限 if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1001); return; } request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName); } // 5. 执行下载 DownloadManager dManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); if (dManager != null) { dManager.enqueue(request); Toast.makeText(MainActivity.this, "开始下载文件", Toast.LENGTH_SHORT).show(); } } });
2. 文件名拼接的低级错误
你原来的代码里:
String fileName = "Документ" + url.startsWith(".");
url.startsWith(".")返回的是布尔值(true/false),导致文件名变成Документtrue或者Документfalse,这显然不是你想要的。上面的方案里用URLUtil.guessFileName已经完美解决了这个问题,它会从URL、响应头里自动解析出正确的文件名。
3. 存储权限的适配细节
- Android 6.0+:必须动态申请
WRITE_EXTERNAL_STORAGE权限,否则DownloadManager无法写入外部存储; - Android 10+:默认启用Scoped Storage,如果你想继续使用公共下载目录,需要在
AndroidManifest.xml的<application>标签里添加:
android:requestLegacyExternalStorage="true"
4. 修正shouldOverrideUrlLoading的返回值
你原来的方法最后返回true,会导致所有非下载链接也被拦截,页面无法正常加载。正确的写法应该是:
@Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // 仅拦截直接的下载链接(可选,因为主要下载逻辑已经交给DownloadListener) if (url.endsWith(".xlsx") || url.endsWith(".xls") || url.endsWith(".pdf") || url.endsWith(".doc")) { // 这里可以复用DownloadListener里的下载逻辑 return true; } // 非下载链接,让WebView正常加载 return false; }
内容的提问来源于stack exchange,提问作者HedgDifuse
相关产品推荐
相关产品推荐

