我可以用 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 才能生效。)
我正在使用 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 才能生效。)