24

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

细节

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

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

其他选项

  1. 下载图像客户端:我们不能这样做,因为 (1) Safari 在大型 base64 URL 上崩溃,并且 (2) Safari 尚不支持锚标签上的下载属性,我需要指定下载的图像文件名。

  2. 使用 a$.get而不是$.post我们不能这样做,因为我们需要将canvas.toDataURL()请求发送到服务器。GET请求 URI 有大小限制。

4

3 回答 3

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 %>"
于 2013-07-08T12:10:12.997 回答
3

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

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

于 2013-05-13T17:12:59.267 回答
1

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

这是使用相同技术的更安全方法的示例。它假设有一个登录的用户拥有一个 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_downloadin的路线routes.rb

get 'ajax_download', to: 'controller#ajax_download'
于 2019-12-03T23:40:21.803 回答