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

如何在WebView中打开不以.pdf结尾的URL对应的PDF文件?

WebView打开无.pdf后缀PDF链接的问题解决

问题分析

当前代码通过谷歌文档代理加载PDF时,旧版Android WebView不支持require-trusted-types-for这个Content-Security-Policy指令,导致页面加载报错无法渲染PDF;同时无.pdf后缀的URL无法直接打开,是因为WebView默认可能无法识别该链接返回的PDF内容类型。

解决方案

1. 自定义WebViewClient处理CSP错误

通过拦截响应头或错误信息,移除不支持的CSP指令,让页面正常加载:

首先定义自定义WebViewClient:

class CustomWebViewClient : WebViewClient() {
    override fun onReceivedHttpError(
        view: WebView?,
        request: WebResourceRequest?,
        errorResponse: WebResourceResponse?
    ) {
        errorResponse?.let { resp ->
            resp.responseHeaders?.let { headers ->
                val cspHeader = headers["Content-Security-Policy"]
                if (!cspHeader.isNullOrEmpty() && cspHeader.contains("require-trusted-types-for")) {
                    // 移除不支持的CSP指令
                    val modifiedCsp = cspHeader.replace("require-trusted-types-for 'script';", "")
                    val newHeaders = headers.toMutableMap().apply {
                        this["Content-Security-Policy"] = modifiedCsp
                    }
                    // 构造修改后的响应
                    val modifiedResponse = WebResourceResponse(
                        resp.mimeType,
                        resp.encoding,
                        resp.statusCode,
                        resp.reasonPhrase,
                        newHeaders,
                        resp.data
                    )
                    super.onReceivedHttpError(view, request, modifiedResponse)
                    return
                }
            }
        }
        super.onReceivedHttpError(view, request, errorResponse)
    }

    override fun onReceivedError(
        view: WebView?,
        request: WebResourceRequest?,
        error: WebResourceError?
    ) {
        error?.let {
            if (it.description.toString().contains("require-trusted-types-for")) {
                return // 忽略该错误
            }
        }
        super.onReceivedError(view, request, error)
    }
}

然后在初始化WebView时使用该Client,并对原URL做编码:

@SuppressLint("SetJavaScriptEnabled")
override fun onCreateFinished() {
    binding.webView.webViewClient = CustomWebViewClient()
    binding.webView.settings.javaScriptEnabled = true
    binding.webView.settings.displayZoomControls = true
    val targetUrl = "你的无.pdf后缀的目标URL"
    // 对原URL进行UTF-8编码,避免特殊字符导致解析错误
    val encodedUrl = URLEncoder.encode(targetUrl, "UTF-8")
    val googleDocsProxy = "https://docs.google.com/gview?embedded=true&url=$encodedUrl"
    binding.webView.loadUrl(googleDocsProxy)
}

2. 直接让WebView识别PDF内容

如果目标URL返回的是PDF文件(只是无后缀),可以拦截请求并明确告知WebView内容类型:

@SuppressLint("SetJavaScriptEnabled")
override fun onCreateFinished() {
    binding.webView.webViewClient = object : WebViewClient() {
        override fun shouldInterceptRequest(
            view: WebView?,
            request: WebResourceRequest?
        ): WebResourceResponse? {
            request?.url?.toString()?.let { url ->
                return try {
                    val connection = URL(url).openConnection()
                    val contentType = connection.contentType
                    if (contentType == "application/pdf") {
                        // 明确指定内容类型为PDF
                        WebResourceResponse(
                            "application/pdf",
                            connection.contentEncoding,
                            connection.inputStream
                        )
                    } else {
                        super.shouldInterceptRequest(view, request)
                    }
                } catch (e: Exception) {
                    super.shouldInterceptRequest(view, request)
                }
            }
            return super.shouldInterceptRequest(view, request)
        }
    }
    binding.webView.settings.javaScriptEnabled = true
    binding.webView.settings.displayZoomControls = true
    binding.webView.loadUrl("你的无.pdf后缀的目标URL")
}

3. 集成第三方PDF库渲染

如果WebView本身不支持PDF渲染(低版本系统),可以先下载PDF文件,再用第三方库(如Android Pdf Viewer)本地渲染:

// 添加依赖:implementation "com.github.barteksc:android-pdf-viewer:3.2.0-beta.1"
// 下载PDF文件后加载到PdfView
PdfView.fromUri(Uri.parse(targetUrl))
    .defaultPage(0)
    .load()

内容的提问来源于stack exchange,提问作者Ahmet Yılmaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 09:05:36