如何使用来自 AJAX 帖子的 Rails send_data 触发下载
Posted
技术标签:
【中文标题】如何使用来自 AJAX 帖子的 Rails send_data 触发下载【英文标题】:How to trigger download with Rails send_data from AJAX post 【发布时间】:2013-04-20 23:27:19 【问题描述】:我正在尝试使用 send_data
返回一个 PNG 图像作为 ajax 发布请求的响应。如何让浏览器在成功回调时触发下载?
详情
我正在使用canvas.toDataURL()
生成一个大型 base64 图像,然后将其发布到 Rails (v3.2.6)。 Rails 将其解码为二进制 PNG,并将图像发送回客户端。
我也试过send_file
,但也有同样的问题。
其他选项
下载图像客户端:我们不能这样做,因为 (1) Safari crashes on large base64 URLs 和 (2) Safari does not yet support the download attribute on anchor tags 我需要指定下载的图像文件名。
使用$.get
代替$.post
: 我们不能这样做,因为我们需要将canvas.toDataURL()
与请求一起发送到服务器。 GET
请求 URI 有大小限制。
【问题讨论】:
然后将来自 AJAX 请求的数据放入会话中,然后通过location.href="..."
指向发送适当标头的脚本触发下载,从会话中传递数据,然后将其删除来自会话。
不确定为什么要使用 AJAX 请求来下载文件。尊重 send_data/send_file 操作的非 AJAX link_to 应该下载图像。
我认为这是一个关于如何将数据下载为文件的http标准。也许使用 content_type: 'image/png' ?
我不得不做同样类型的事情,最后只是解码和保存图像服务器端,然后在 javascript 中使用 window.open 打开一个窗口,该窗口使用服务器中的 send_file 来获取图像,然后只需删除服务器上的临时图像。
【参考方案1】:
在控制器中创建一个函数
def ajax_download
send_file "path_to_file/" + params[:file]
end
然后在控制器动作中
respond_to do |format|
@java_url = "/home/ajax_download?file=#file_name"
format.js render :partial => "downloadFile"
end
并使用 _downloadFile.js.erb 创建部分视图文件夹名称并写下这一行
window.location.href = "<%=@java_url %>"
【讨论】:
您可能想要制作一个 iframe 并将其位置设置为文件的 URL。无论哪种方式,这都是一个可靠的解决方案。 @mayatron 请批准这个 在这里为我工作:) 值得一提的是,在send_file
中使用params[:file]
是未经处理的,可能会导致数据被盗。【参考方案2】:
您不能从 JS 下载文件到磁盘。这是一个安全问题。请参阅下面的博客文章了解一个很好的解决方法。
http://johnculviner.com/post/2012/03/22/Ajax-like-feature-rich-file-downloads-with-jQuery-File-Download.aspx
【讨论】:
您可以将画布图像下载为 base64,只要图像没有被污染。这有一些限制,例如设置文件名。工作示例:greenethumb.com/article/1429/…【参考方案3】:不要不要只是复制并粘贴已接受的答案。这是一个不可低估的巨大安全风险。尽管这项技术很聪明,但根据任何人都可以输入的参数来传递文件,就可以访问任何人可以想象到的任何文件。
这是使用相同技术的更安全方法的示例。它假设有一个登录的用户拥有 API 令牌,但您应该能够根据自己的场景调整它。
在行动中:
current_user.pending_download = file_name
current_user.save!
respond_to do |format|
@java_url = "/ajax_download?token=#current_user.api_token"
format.js render :partial => "downloadFile"
end
在控制器中创建一个函数
def ajax_download
if params[:token] == current_user.api_token
send_file "path_to_file/" + current_user.pending_download
current_user.pending_download = ''
current_user.save!
else
redirect_to root_path, notice: "Unauthorized"
end
end
使用 _downloadFile.js.erb 创建部分视图文件夹名称
window.location.href = "<%=@java_url %>"
当然,您需要一条指向/ajax_download
in routes.rb
的路由
get 'ajax_download', to: 'controller#ajax_download'
【讨论】:
以上是关于如何使用来自 AJAX 帖子的 Rails send_data 触发下载的主要内容,如果未能解决你的问题,请参考以下文章
判断帖子是不是来自codeigniter中的ajax调用的方法?