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

Wicked PDF生成PDF时图片无法显示问题求助(Ruby on Rails环境)

问题根因与解决方案

核心问题原因

  • Wicked PDF 依赖的 wkhtmltopdf 工具在后台渲染时不携带当前用户的会话cookie,你浏览器能访问图片是因为处于登录态,而wkhtmltopdf请求需要认证的Active Storage资源时会被权限拦截返回404
  • 默认url_for生成的是相对路径,wkhtmltopdf无法解析非绝对路径的资源地址
  • 部分旧版本wkhtmltopdf不支持webp等新式图片格式

解决方案

方案1:直接嵌入Base64图片(最稳妥,全环境兼容)

直接把图片转成Base64编码嵌入HTML,完全不需要外部资源请求,不会出现路径、权限问题。修改视图中的图片标签代码:

<%# 品牌logo部分修改 %>
<% if @certificate.certificate_template.brand_logo.attached? %>
  <% logo_blob = @certificate.certificate_template.brand_logo.blob %>
  <%= wicked_pdf_image_tag "data:#{logo_blob.content_type};base64,#{Base64.strict_encode64(logo_blob.download)}", width: '400px' %>
<% elsif current_tenant && current_tenant.has_custom_domain? && @theme && @theme.brand_logo.attached? %>
  <% logo_blob = @theme.brand_logo.blob %>
  <%= wicked_pdf_image_tag "data:#{logo_blob.content_type};base64,#{Base64.strict_encode64(logo_blob.download)}", width: '400px' %>
<% end %>

<%# 签名部分修改 %>
<% if @certificate.certificate_template.signature.attached? %>
  <% sign_blob = @certificate.certificate_template.signature.blob %>
  <%= wicked_pdf_image_tag "data:#{sign_blob.content_type};base64,#{Base64.strict_encode64(sign_blob.download)}", width: '400px' %>
<% end %>

方案2:生成带完整协议的绝对路径

如果不想用Base64,需要在渲染模板时强制生成绝对路径,修改控制器中render_to_string和pdf渲染的代码,补充host配置:

# controllers/admin/certificates_controller.rb
def view_pdf
  @certificate = Certificate.find(params[:certificate_id])
  # 统一配置渲染的host参数,确保生成绝对路径
  render_options = {
    host: request.host,
    port: request.port,
    protocol: request.protocol
  }
  if !@certificate.pdf.attached?
    pdf = WickedPdf.new.pdf_from_string(
      render_to_string(
        template: 'admin/certificates/view_pdf.html.erb',
        layout: 'application.pdf.erb',
        **render_options
      )
    )
    @certificate.pdf.attach(io: StringIO.new(pdf), filename: "#{@certificate.path.title} - #{@certificate.user.name}.pdf", content_type: 'application/pdf')
  end
  
  respond_to do |format|
    format.html
    format.pdf do 
      render(
        pdf: url_for(@certificate.pdf),
        content_type: 'application/pdf',
        template: 'admin/certificates/view_pdf.html.erb',
        page_size: 'A4',
        layout: 'application.pdf.erb',
        orientation: 'Landscape',
        zoom: 1,
        dpi: 75,
        disposition: 'inline',
        **render_options
      )
    end
  end
end

同时可以给Active Storage资源生成公开可访问的临时链接,避免权限拦截:

<%= wicked_pdf_image_tag @certificate.certificate_template.brand_logo.blob.signed_url(expires_in: 5.minutes), width: '400px' %>

开发环境额外检查

如果是在本地开发环境测试,需要确保config/environments/development.rb中开启静态资源服务:

config.serve_static_files = true

同时检查wkhtmltopdf版本是否支持你使用的图片格式,避免使用webp等新式格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 06:42:00