如何将文件 url 传递给中间人的辅助方法

How to pass file url to helper method in middleman

我正在编写一个辅助方法,以便在需要时将图像转换为 base64 字符串。下面是代码

  # config.rb
  helpers do
    def base64_url(img_link, file_type: "jpg")
      require "base64"
      if file_type =="jpg"
        "data:image/jpg;base64,#{Base64.encode64(open(img_link).to_a.join)}"
      elsif file_type =="png"
        "data:image/jpg;base64,#{Base64.encode64(open(img_link).to_a.join)}"
      else
        link
      end
    end
  end

在page.html.erb

<%= image_tag base64_url('/images/balcozy-logo.jpg') %>

现在的问题是当 ruby 读取 '/images/balcozy-logo.jpg' 它从系统根目录而不是项目根目录读取文件。

错误信息如下

Errno::ENOENT at /
No such file or directory @ rb_sysopen - /images/balcozy-logo.jpg

如何解决这个问题并从 project_root/source/images

传递正确的图像 url

在 Middleman app.root returns 应用程序的根目录。还有 app.root_path,它的作用相同,但 return 是一个 Pathname 对象,稍微方便一些:

full_path = app.root_path.join("source", img_link.gsub(/^\//, ''))

如果 img_link/ 开头,则 gsub 是必需的,因为它将被解释为文件系统的根目录。

我冒昧地对你的方法做了一些修改:

require "base64"

helpers do
  def base64_url(path, file_type: "jpg")
    return path unless ["jpg", "png"].include?(file_type)

    full_path = app.root_path.join("source", path.gsub(/^\//, ''))

    data_encoded = File.open(full_path, 'r') do |file|
      Base64.urlsafe_encode64(file.read)
    end

    "data:image/#{file_type};base64,#{data_encoded}"
  end
end

我在这里做了一些事情:

  1. 移动require "base64"到文件顶部;它不属于方法内部。

  2. 在方法的最开始检查file_type,如果不在列出的类型中,则尽早检查return。

  3. 而不是 open(filename).to_a.join(或更简洁的 open(filename).read),使用 File.open。 OpenURI(提供您正在使用的 open 方法)对于从本地文件系统读取来说是多余的。

  4. 使用 Base64.urlsafe_encode64 而不是 encode64。可能没有必要,但也无妨。

  5. 删除不需要的if;因为我们知道 file_type 将是 jpgpng 我们可以直接在数据 URI 中使用它。

可能有更优雅的方法来获取 file_path 或使用 Middleman 的 built-in 资产系统确定文件的 MIME 类型,但是对文档的非常简短的搜索没有找到任何结果。