我可以用 json 渲染图像吗?

Can I render an image with json?

我正在使用 Typeahead 在下拉列表中呈现我的 "User" 模型的实例:

控制器:

def typeahead
  render json: User.where(name: params[:query])
end

查看:

<input type="text" id="typeahead">
<script type="text/javascript">
  var bloodhound = new Bloodhound({
    datumTokenizer: function (d) {
      return Bloodhound.tokenizers.whitespace(d.value);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,

    remote: '/typeahead/%QUERY', 
    limit: 50
  });
  bloodhound.initialize();

  $('#typeahead').typeahead(null, {
    displayKey: 'name',
    source: bloodhound.ttAdapter()
  });

  $('#typeahead').bind('typeahead:selected', function(event, datum, name) {
    doSomething(datum.id);
  });
</script>

此代码会导致 User.name 的列表在我键入时下拉。

我可以渲染图像吗,在这种情况下 User.avatar.url(:thumb)?当我将 displayKey: 'name', 更改为 displayKey: 'avatar.url(:thumb)', 时,下拉列表只会为每个用户显示 "undefined"。

[我确保 User.avatar.url(:thumb) 在其他地方成功显示]

您需要在服务器上将图像编码为 base64,然后 return 在您的 json 响应中生成结果字符串,最后在客户端使用此 base64 字符串填充您的图像

1- 服务器端:将图像编码为 base64

def typeahead
  users = User.where(name: params[:query])

  json = users.collect do |user|
    path = user.avatar.url(:thumb)
    image = open(path) { |io| io.read }
    base64 = ActiveSupport::Base64.encode64(image)

    {id: user.id, name: user.name, base64: base64}
  end

  render json: json
end

2- 客户端:使用模板填充用户名和图像

$('#typeahead').typeahead(null, {
  displayKey: 'name',
  source: bloodhound.ttAdapter()
  templates: {
    suggestion: Handlebars.compile('<p><img src="data:image/png;base64,{{base64}}">{{name}}</p>')
  }
});

注意 1:未经测试,您可能需要做一些小的调整

注意 2:当您有大量用户 table 和大量并发连接时,这将需要您的服务器提供大量功能,因为服务器必须为每个查询打开和编码许多图像文件.

displayKey 属性告诉 Typeahead 要显示 JSON 响应 的哪个(字符串)字段,因此它只能指向现有的 JSON 属性,例如name.

我建议不要渲染图像,而是提供其 URL 作为响应的一部分,然后在浏览器中渲染它。

例如,您可以向 User 模型添加一个新方法:

def thumb_url
  avatar.url(:thumb)
end

将该方法的结果添加到控制器的响应中:

def typeahead
  render json: User.where(name: params[:query]), methods: :thumb_url
end

然后在 Typeahead template 中使用响应而不是 displayKey,例如

$('#typeahead').typeahead(null, {
  source: bloodhound.ttAdapter()
  templates: {
    suggestion: Handlebars.compile('<p><img src="{{thumb_url}}">{{name}}</p>')
  }
});

(请注意,您必须添加 Handlebars 才能生效。)