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

OpenHtmlToPdf无外网加载外部资源致转换卡住如何配置忽略

OpenHtmlToPdf 外链资源加载失败跳过方案

OpenHtmlToPdf 没有提供一键跳过所有外部资源的配置开关,但可以通过自定义URI解析器实现外链加载超时自动降级、不阻塞PDF生成的需求,最终可以正常输出存在资源缺失的PDF文件,不会出现进程挂起问题。

问题根因

默认配置下,OpenHtmlToPdf 加载HTTP/HTTPS外链资源时没有设置连接、读取超时,当服务器防火墙拦截网络请求、TCP连接无响应时,加载线程会一直阻塞等待响应,直到系统级TCP超时触发,表现为转换进程挂起。

实现代码

通过重写FSUriResolver自定义资源加载逻辑,给外链请求设置短超时,加载失败时返回空流让渲染流程继续:

import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
import com.openhtmltopdf.extend.FSStream;
import com.openhtmltopdf.extend.FSUriResolver;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;

public class PdfConvertConfig {
    public static void configUriResolver(PdfRendererBuilder builder) {
        builder.useUriResolver(new FSUriResolver() {
            // 外链加载超时时间设为3秒,可根据实际环境调整
            private static final int RESOURCE_TIMEOUT_MS = 3000;

            @Override
            public FSStream resolveUri(String baseUri, String resourceUri) {
                // 仅对HTTP/HTTPS外链做特殊处理
                if (resourceUri.startsWith("http://") || resourceUri.startsWith("https://")) {
                    HttpURLConnection connection = null;
                    try {
                        URI targetUri = URI.create(resourceUri);
                        connection = (HttpURLConnection) targetUri.toURL().openConnection();
                        connection.setConnectTimeout(RESOURCE_TIMEOUT_MS);
                        connection.setReadTimeout(RESOURCE_TIMEOUT_MS);
                        connection.setInstanceFollowRedirects(false);
                        connection.setRequestMethod("GET");
                        connection.connect();
                        
                        if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                            InputStream resourceStream = connection.getInputStream();
                            return new FSStream() {
                                @Override
                                public InputStream getStream() {
                                    return resourceStream;
                                }
                                @Override
                                public String getReader() {
                                    return null;
                                }
                            };
                        }
                    } catch (Exception ignored) {
                        // 所有网络异常(拦截、超时、资源不存在等)直接走降级逻辑
                    } finally {
                        if (connection != null) {
                            connection.disconnect();
                        }
                    }
                    // 外链加载失败返回空流,渲染时自动跳过该资源,不会中断转换
                    return new FSStream() {
                        @Override
                        public InputStream getStream() {
                            return new ByteArrayInputStream(new byte[0]);
                        }
                        @Override
                        public String getReader() {
                            return null;
                        }
                    };
                }
                // 本地类路径、文件系统资源走默认加载逻辑
                return null;
            }
        });
    }
}

调用时只需要在创建PdfRendererBuilder实例后,传入该方法配置解析器,后续正常绑定HTML源、输出流执行转换即可。

优化建议

  • 如果业务场景完全不需要加载任何外网资源,可以直接在外链判断分支返回空流,跳过所有网络请求,彻底避免网络相关阻塞,转换效率更高。
  • 需要提示资源缺失的场景,可以将返回的空流替换为本地预置的占位图输入流,PDF中对应资源位置会显示占位提示。
  • 不要修改本地资源的加载逻辑,避免影响正常的本地图片、样式表、字体文件加载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 21:03:19