You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android DownloadManager从WebView下载MP4文件后缀自动变为.bin问题

Android DownloadManager 下载MP4文件后缀变为.bin的解决方案

根因说明

  • 你代码中request.setMimeType(mimetype)传入的是服务器返回的application/octet-stream,并未真正覆盖为正确的video/mp4类型
  • 旧版本Android系统的DownloadManager会优先读取服务器响应的Content-Type,当类型为通用二进制流application/octet-stream时,即使你传入的文件名带.mp4后缀,系统也会强制修正后缀为.bin
  • URLUtil.guessFileName方法受传入的MIME类型影响,当传入类型为application/octet-stream时,部分场景下会自动将后缀替换为.bin,即使Content-Disposition头中存在正确的.mp4文件名

修复步骤

1. 手动提取并校验文件名

优先从Content-Disposition头中提取文件名,避免依赖系统的guess逻辑,同时强制校验文件名后缀为.mp4

2. 强制覆盖正确的MIME类型

根据文件后缀手动指定正确的MIME类型,不要直接使用服务器返回的application/octet-stream

3. 正确配置WebView的下载监听

WebView的下载事件需要通过DownloadListener接管,不要仅依赖shouldOverrideUrlLoading处理跳转逻辑

修复后的代码示例

DownloadManager 下载逻辑修改

// 从contentDisposition中提取真实文件名
String fileName = "";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    try {
        ContentDisposition contentDispositionObj = ContentDisposition.parse(contentDisposition);
        fileName = contentDispositionObj.getFilename();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    }
} else {
    // 低版本系统正则匹配文件名
    Pattern pattern = Pattern.compile("filename=\"(.*?)\"");
    Matcher matcher = pattern.matcher(contentDisposition);
    if (matcher.find()) {
        fileName = matcher.group(1);
    }
}
// 提取失败时fallback到系统方法
if (TextUtils.isEmpty(fileName)) {
    fileName = URLUtil.guessFileName(url, contentDisposition, mimetype);
}
// 强制校验文件名后缀
if (!fileName.toLowerCase().endsWith(".mp4")) {
    fileName += ".mp4";
}

// 覆盖为正确的MIME类型
String finalMimeType = mimetype;
if (fileName.toLowerCase().endsWith(".mp4")) {
    finalMimeType = "video/mp4";
}

// 构建下载请求
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
String cookies = CookieManager.getInstance().getCookie(url);
request.addRequestHeader("cookie", cookies);
request.setMimeType(finalMimeType);
request.addRequestHeader("User-Agent", userAgent);
request.setTitle(fileName);
request.setDescription("Downloading File...");
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
// 传入校验后的文件名
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
request.allowScanningByMediaScanner();

DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);

WebView 配置修改

// 给WebView设置下载监听器,接管下载事件
webView.setDownloadListener(new DownloadListener() {
    @Override
    public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
        // 调用上述修改后的下载逻辑即可
        startDownload(url, userAgent, contentDisposition, mimetype);
    }
});

WebViewClient 优化(可选)

原有shouldOverrideUrlLoading逻辑会接管所有页面跳转,可优化为仅处理非HTTP/HTTPS链接:

@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    Uri uri = request.getUrl();
    String scheme = uri.getScheme();
    if (scheme == null || (!scheme.startsWith("http") && !scheme.startsWith("https"))) {
        try {
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
            return true;
        } catch (Exception e) {
            // 无对应处理应用时忽略
        }
    }
    view.loadUrl(uri.toString());
    return true;
}

内容的提问来源于stack exchange,提问作者zarez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 21:00:03