从 PDF 中读取文本在 Rails 控制台中有效,但在 Rails 应用程序中无效

Reading text from a PDF works in Rails console but not in Rails application

我有一个简单的单页可搜索 PDF,它使用 Active Storage 上传到 Rails 6 应用模型(汽车)。我可以使用 Rails 控制台中的 'tempfile' 和 'pdf-reader' gem 从 PDF 中提取文本:

> @car.creport.attached?
=> true
> f = Tempfile.new(['file', '.pdf'])
> f.binmode
> f.write(@car.creport.blob.download)
> r = PDF::Reader.new(f.path.to_s)
> r.pages[1].text
=> "Welcome to the ABC Car Report for January 16, 20...

但是,如果我在我的 cars_controller.rb 的创建方法中尝试同样的事情,它不起作用:

# cars_controller.rb
...
  def create
    @car = Car.new(car_params)
    @car.filetext = ""
    f = Tempfile.new(['file', '.pdf'])
    f.binmode
    f.write(@car.creport.blob.download)
    r = PDF::Reader.new(f.path.to_s)
    @car.filetext = r.pages[1].text
    ...
  end

当我 运行 Rails 应用程序时,我可以创建一辆新汽车和 select 一个要附加的 PDF 文件。但是当我单击 'Submit' 时,我在 f.write() 行的 cars_controller.rb 中得到一个 FileNotFoundError。

我的直觉是,控制器正在尝试读取 blob,以便过早地将其写入临时文件(即,甚至在写入 blob 之前)。我尝试插入一个 sleep(2) 来给它时间,但我得到了相同的 FileNotFoundError。

有什么想法吗?

谢谢!

差异似乎与您的 @car 变量有关。

在控制台中,您附加了一个 blob (@car.creport.attached? => true)。在您的控制器中,您正在初始化 Car class 的一个新实例,因此除非您正在进行一些在后台附加某些内容的初始化,否则它将为 nil。

为什么会 return 出现 'file not found' 错误我不确定,但据我所知,这是代码示例之间的唯一区别。您正在尝试编写 @car.creport.blob.download,它出现在控制台的 @car 上,但在您的控制器中为 nil。

我不明白你为什么要经历这么多困难。在没有块的情况下使用 .download 会将整个文件加载到内存中(哎呀)。如果 @car.creport 是 ActiveStorage 附件,您可以只使用 open method 代替:

@car.creport.blob.open do |file|
  file.binmode
  r = PDF::Reader.new(file) # just pass the IO object
  @car.filetext = r.pages[1].text
end if @car.creport

这会将文件传输到磁盘(作为临时文件)。

如果您只是通过普通的旧文件输入进行文件输入,您将在参数中得到一个 ActionDispatch::Http::UploadedFile,它也非常容易打开:

params[:file].open do |file|
  file.binmode
  r = PDF::Reader.new(file) # just pass the IO object
  @car.filetext = r.pages[1].text
end if params[:file].respond_to?(:open)