【问题标题】:How to pass file url to helper method in middleman如何将文件url传递给中间人的帮助方法
【发布时间】:2016-01-21 15:25:27
【问题描述】:

我正在编写一个辅助方法来在需要时将图像转换为 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 传递正确的图片网址

【问题讨论】:

  • 您知道您的if 的两个分支中都有data:image/jpg 吗?

标签: ruby middleman


【解决方案1】:

在 Middleman app.root 返回应用程序的根目录。还有app.root_path,作用相同,但返回一个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,如果不在列出的类型中,则提前返回。

  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 的内置资产系统确定文件的 MIME 类型,但对文档进行非常简短的搜索并没有发现任何问题。

【讨论】:

  • 非常感谢您为此付出的努力。我必须改变两件事才能使它工作。 full_path 行错过了源目录,因此找不到文件,所以我尝试了这个 full_path = app.root_path + "#{:source}" + path.gsub(/^\//, '') 并且它有效。由于某种原因urlsafe_encode64(file.read) 编码不起作用,所以继续使用encode64(file.read) 现在它工作得很好。还用png测试过,一切都很好。再次感谢:)
  • 标记为已接受的答案,请为以后来的人更新代码。我本可以这样做,但我希望你能做到这一点:)
  • :source只是一个符号,是Ruby中一种特殊的字符串,所以"#{:source}"等价于:source.to_s,也就是"source"。我已更新我的答案以使用 app.root_path.join("source", path.gsub(...)) 而不是 app.root_path + path.gsub(...)
  • 我使用了:source,假设它与中间人配置中的源相同,我想如果用户为项目设置了不同的源文件夹,sn-p 仍然可以播放,所以我使用了@ 987654354@ 而不是硬编码source 目录。顺便说一句,您在 full_path 行中缺少右括号;)
  • 不,:sourceSymbol,而不是变量或方法。 :foo.to_s 将始终返回 "foo"(而 "foo".to_sym 将返回 :foo)。
猜你喜欢
  • 1970-01-01
  • 2022-12-07
  • 2012-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多