Rails项目中Prawn加载外部图片报错:No such file or directory @ rb_sysopen
解决Prawn加载外部图片报错
No such file or directory @ rb_sysopen的问题 问题核心
这个错误的本质是open(@foo.image.url)没有正确解析成外部资源的IO流,反而被当成本地文件路径查找,因此触发了文件不存在的错误。常见诱因有两个:
@foo.image.url返回的是相对路径而非完整外部URL(比如仅返回/uploads/image.jpg,而非https://yourdomain.com/uploads/image.jpg)open调用未正确处理二进制资源,返回的对象不符合Prawn的image方法要求
解决方案
1. 确保图片URL是完整绝对路径
先在控制台打印@foo.image.url,确认输出是带http://或https://的完整外部地址。如果是相对路径,需根据你使用的附件上传gem生成绝对URL:
# Active Storage 示例: absolute_image_url = rails_blob_url(@foo.image, only_path: false) # CarrierWave 示例: absolute_image_url = @foo.image.url(host: Rails.application.config.action_controller.default_url_options[:host])
2. 正确使用open加载外部图片
需以二进制模式打开外部资源,同时确保返回的IO对象能被Prawn识别。修正后的PDF类代码:
class ExamplePdf < Prawn::Document require 'open-uri' def initialize(foo) super() @foo = foo letter end def letter # 获取完整绝对图片URL(根据你的附件gem调整) absolute_image_url = rails_blob_url(@foo.image, only_path: false) # 以二进制模式打开外部资源并传递给Prawn URI.open(absolute_image_url, 'rb') do |image_io| image image_io, scale: 0.5 end end end
注:Ruby 2.6+推荐用
URI.open替代直接open,避免命名冲突同时提升安全性。
3. 额外排查点
- 检查服务器是否能正常访问该外部URL(比如防火墙、代理设置限制)
- 如果使用Active Storage,确保
config.active_storage.service配置的存储服务(如S3)URL是公开可访问的
控制器调用无需修改
你当前的控制器代码逻辑正常,保持原样即可:
pdf = CombinePDF.new letter = ExamplePdf.new(@foo).render pdf << CombinePDF.parse(letter)
内容的提问来源于stack exchange,提问作者Dustin
相关产品推荐
相关产品推荐

