首页 > 解决方案 > Rails ActiveStorage 问题:rails_blob_path 的“找不到文件”错误,即使路径手动工作

问题描述

我有一个在本地运行良好的小型 Rails 应用程序,使用 ActiveStorage 上传 docx 文件并将其转换为 html(以及其他内容)。要将其部署到 Heroku,我需要从使用本地文件系统进行存储更改为使用 S3,从而更改生成文件路径的方式。

我的研究表明rails_blob_path(或_url)应该是我需要的,但我收到“找不到文件”错误,即使文件路径在我手动尝试时有效。

如何为可用于进一步转换的附件生成路径?文档说这很简单,但我无法让它工作!


我的应用程序有项目,每个项目都必须通过 ActiveStorage 附加一个文件。创建项目后(及其附件),文件被处理并将其内容显示给用户(从 Word 文件中提取文本,将其与单词列表进行匹配并存储生成的 HTML 和单词列表以供进一步使用由用户编辑)。

我最初的方法是在项目模型中使用这种方法:

def real_file_path
  ActiveStorage::Blob.service.send(:path_for, file.key)
end

然后,在控制器中,我调用了这个方法来进行实际的转换:

def convert_docx_file
  _file_contents = ''
  _doc = Docx::Document.open(@project.real_file_path)
  _doc.paragraphs.each do |p|
    _file_contents += p.to_html
  end
  @project.update_attributes(file_contents: _file_contents)
end

(这使用 DOCX gem 创建一个合适的对象,然后对其进行迭代并将段落转换为 HTML。)

现在有问题的步骤是创建 _doc 对象。上面的代码在本地文件系统上运行良好。对于 S3 的使用,经过大量的研究和实验,我将其更改为:

.
.
  _doc = Docx::Document.open(rails_blob_path(@project.file))
.
.
.

在我的本地机器上运行时,这会产生错误:Zip::Error in ProjectsController#show File /rails/active_storage/blobs/BLAH_BLAH_BLAH/original%20file.docx not found. 但是,当我将地址复制并粘贴到浏览器中时,它可以正常下载。

谁能让我知道如何获得正确的文件路径,以便我可以再次进行转换?

标签: ruby-on-railsruby-on-rails-5

解决方案


所以,最后,我通过在服务类中创建一个下载器来回避这个问题,我将把这些细节留给可能有同样问题的其他人。

控制器中的相关行现在是:

_doc = DocxDownloadService.new(@project.file).doc

服务类 ( app/services/docx_download_service.rb) 或多或少直接来自 ActiveStorage 文档:

class DocxDownloadService
  include ActiveStorage::Downloading
  attr_reader :blob

  def initialize(blob)
    @blob = blob
  end

  def doc
    download_blob_to_tempfile do |file|
      Docx::Document.open(file)
    end
  end
end

这在本地(在我的文件系统上)和使用 S3 的服务器上都有效。


推荐阅读