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

Rails应用自动为上传PDF、图片加密码并存至AWS S3的技术咨询

解决方案

一、为用户上传的PDF添加密码保护

你已经用Prawn实现了系统生成PDF的加密,但Prawn更适合创建新PDF,处理已上传的现有PDF,推荐使用纯Ruby实现的HexaPDF库(无需依赖外部工具),具体步骤如下:

  1. 把HexaPDF加入Gemfile:
gem 'hexapdf'

执行bundle install完成安装。

  1. 编写加密逻辑(可放在上传处理的Controller或Service类中):
# uploaded_file为用户上传的PDF文件对象,user为当前用户实例
def encrypt_uploaded_pdf(uploaded_file, user)
  # 基于用户数据生成密码,示例:用户ID+8位随机字符串
  password = "#{user.id}_#{SecureRandom.hex(8)}"
  
  # 加载上传的PDF文件
  doc = HexaPDF::Document.open(uploaded_file.path)
  
  # 设置密码保护:user_password是打开密码,owner_password用于修改权限
  doc.security.set_password(user_password: password, owner_password: SecureRandom.hex(16))
  
  # 生成加密后的临时文件
  encrypted_pdf_path = "#{Dir.tmpdir}/encrypted_#{SecureRandom.uuid}.pdf"
  doc.write(encrypted_pdf_path)
  
  # 上传加密后的文件到AWS S3(复用你已有的S3上传逻辑)
  s3_object = Aws::S3::Object.new(bucket_name: '你的存储桶名称', key: "protected_pdfs/#{user.id}/#{SecureRandom.uuid}.pdf")
  s3_object.upload_file(encrypted_pdf_path)
  
  # 将密码存入数据库,方便后续提供给用户
  user.update!(pdf_password: password)
  
  # 清理临时文件
  File.delete(encrypted_pdf_path) if File.exist?(encrypted_pdf_path)
  
  s3_object.public_url # 返回加密文件的S3访问地址
end

如果偏好使用外部工具pdftk,也可以通过系统命令调用(需服务器预先安装pdftk),示例代码:

def encrypt_with_pdftk(uploaded_file, user)
  password = "#{user.id}_#{SecureRandom.hex(8)}"
  output_path = "#{Dir.tmpdir}/encrypted_pdf.pdf"
  
  # 执行pdftk加密命令
  system("pdftk #{uploaded_file.path} output #{output_path} user_pw #{password}")
  
  # 后续上传S3、保存密码逻辑同上
end

二、图片文件的密码保护方案

绝大多数图片格式(JPG、PNG、GIF等)不支持原生密码保护,可行方案是先将图片转换为PDF,再为PDF添加密码保护,具体步骤:

  1. 加入图片处理库mini_magick到Gemfile:
gem 'mini_magick'

执行bundle install完成安装。

  1. 图片转PDF并加密的示例代码:
def protect_image_with_password(uploaded_image, user)
  # 生成密码
  password = "#{user.id}_#{SecureRandom.hex(8)}"
  
  # 用MiniMagick将图片转换为PDF
  pdf_path = "#{Dir.tmpdir}/image_to_pdf_#{SecureRandom.uuid}.pdf"
  image = MiniMagick::Image.open(uploaded_image.path)
  image.format('pdf')
  image.write(pdf_path)
  
  # 复用HexaPDF加密逻辑处理生成的PDF
  doc = HexaPDF::Document.open(pdf_path)
  doc.security.set_password(user_password: password, owner_password: SecureRandom.hex(16))
  encrypted_pdf_path = "#{Dir.tmpdir}/encrypted_image_pdf_#{SecureRandom.uuid}.pdf"
  doc.write(encrypted_pdf_path)
  
  # 上传到AWS S3
  s3_object = Aws::S3::Object.new(bucket_name: '你的存储桶名称', key: "protected_images/#{user.id}/#{SecureRandom.uuid}.pdf")
  s3_object.upload_file(encrypted_pdf_path)
  
  # 保存密码到数据库
  user.update!(image_pdf_password: password)
  
  # 清理临时文件
  File.delete(pdf_path) if File.exist?(pdf_path)
  File.delete(encrypted_pdf_path) if File.exist?(encrypted_pdf_path)
  
  s3_object.public_url
end

你也可以直接用Prawn把图片插入新PDF再加密,示例:

def protect_image_with_prawn(uploaded_image, user)
  password = "#{user.id}_#{SecureRandom.hex(8)}"
  pdf_path = "#{Dir.tmpdir}/prawn_image_pdf.pdf"
  
  Prawn::Document.generate(pdf_path, password: password) do |pdf|
    pdf.image uploaded_image.path, fit: [500, 700] # 适配PDF页面尺寸
  end
  
  # 后续上传S3、保存密码逻辑同上
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 03:55:15