You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Rails 5中用Wicked-PDF生成PDF直接上传AWS S3遇报错问题

解决Wicked-PDF生成的PDF直接上传AWS S3的问题

问题原因

你碰到的ArgumentError: string contains null byte错误,本质是因为Aws::S3::Object#upload_file这个方法是专门用来上传本地文件的——它接受的参数是本地文件路径字符串,或者一个File对象。当你直接把Wicked-PDF生成的二进制PDF字符串传进去时,SDK会误把这个二进制内容当作文件路径去解析,而PDF二进制里的null字节会导致路径解析失败,所以抛出了错误。

解决方案:直接上传二进制内容(无需本地存储)

完全不需要先把PDF存到本地文件夹,直接用S3 SDK的put方法就能上传生成的二进制字符串,这是更高效的方式:

# 生成PDF二进制字符串
pdf = render_to_string pdf: "some_file_name", template: "invoices/download", encoding: "UTF-8"

# 初始化S3资源
s3 = Aws::S3::Resource.new(region: ENV['AWS_REGION'])
obj = s3.bucket('bucket-development').object('your-invoice-filename.pdf')

# 直接上传PDF内容,同时指定正确的文件类型
obj.put(
  body: pdf,
  content_type: 'application/pdf', # 让S3正确识别这是PDF文件
  content_disposition: 'attachment; filename="your-invoice-filename.pdf"' # 可选:设置用户下载时显示的文件名
)

为什么存本地后上传能成功?

当你把PDF内容写入本地文件,再把文件路径传给upload_file时,SDK会正确读取这个本地文件的二进制内容,而不是把路径当作内容解析,自然就不会触发null字节的错误。但直接上传内容省去了本地文件的写入、清理步骤,显然更简洁高效。

额外小提示

  • 如果你的发票PDF体积特别大,可以考虑用S3的分块上传功能,但普通发票的大小用put方法完全足够。
  • 记得确认你的AWS权限配置正确,应用需要拥有目标S3桶的PutObject权限。

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

火山引擎 最新活动