如何从AJAX帖子中使用Rails send_data触发下载

时间:2013-04-26 17:50:12

标签: ruby-on-rails ajax ruby-on-rails-3 jquery canvas

我正在尝试使用send_data返回PNG图像作为ajax发布请求的响应。如何让浏览器触发成功回调下载?

详细信息

我正在使用canvas.toDataURL()生成一个大的base64图像,然后将其发布到Rails(v3.2.6)。 Rails将其解码为二进制PNG,并将图像发送回客户端。

我也试过send_file,但它有同样的问题。

其他选项

  1. 下载图像客户端:我们无法执行此操作,因为(1)Safari crashes on large base64 URLs和(2)Safari does not yet support the download attribute on anchor tags我需要指定下载图像文件名。

  2. 使用$.get代替$.post :我们无法执行此操作,因为我们需要将带有请求的canvas.toDataURL()发送给服务器。 GET请求URI具有大小限制。

3 个答案:

答案 0 :(得分:22)

在控制器中创建一个函数

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 %>"

答案 1 :(得分:3)

您无法从JS将文件下载到磁盘。这是一个安全问题。请参阅下面的博客文章,了解一个好的解决方法。

http://johnculviner.com/post/2012/03/22/Ajax-like-feature-rich-file-downloads-with-jQuery-File-Download.aspx

答案 2 :(得分:0)

不要复制并粘贴接受的答案。这是一个不可低估的巨大安全风险。尽管这项技术很聪明,但是根据任何人都可以输入的参数来传送文件,可以访问任何人都可以想象的文件。

这是使用相同技术的更安全方式的示例。假定有一个具有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中的routes.rb的路线

get 'ajax_download', to: 'controller#ajax_download'