这是我认为我需要用于链接的代码:
<%= link_to'下载文件',:action => “download_file”%>
这会引发错误:
ResourcesController#show中的ActiveRecord :: RecordNotFound
无法找到id = download_file的资源
当我更改链接时,它会在浏览器中打开文件:
<%= link_to'打开文件',resource.document_url,:target => “_blank”%>
在我的ResourcesController中,我定义了这个方法:
def download_file @resource = Resource.find(params[:id]) send_file(@resource.file.path,:filename => @resource.file.name,:type => @resource.file.content_type,:disposition => 'attachment',:url_based_filename => true) end
我在routes.rb中设置了一条路由,如下所示:
resources :resources do get 'resources',:on => :collection end
因此,基于此错误,似乎我在ResourcesController中的download_file方法无法确定与文档关联的资源记录的ID.
我在跑:
Rails 3.2.11
Carrierwave 0.8.0
Ruby 1.9.3-p194
解决方法
download_file方法正确地位于ResourcesController中,但我没有使用正确的变量名.这是我的目的正确的方法定义:
def download_file @resource = Resource.find(params[:id]) send_file(@resource.document.path,:type => 'application/pdf',:url_based_filename => true) end
在我的情况下,我在变量@resource中返回了一个记录,其中有一个与之关联的文档(同样,我使用的是Carrierwave).所以send_file需要的第一个参数是路径(参见API for send_file).此路径信息由@ resource.document.path提供.
send_file接受许多其他参数,这些参数似乎是可选的,因为我只需要其中的三个.有关其他参数,请参阅API文档.
其中一个为我抛出错误的是类型:我传递了变量“@ resource.file.content_type”,但它显然正在寻找文字.一旦我通过它application / pdf,它就有效了.如果没有明确设置,则下载的文件未添加文件扩展名.在任何情况下,对于我的应用程序,这个文档可能是各种不同的mime类型,从pdf到word到mp4.所以我不确定如何指定多个.
对于我的目的(下载而不是在浏览器中显示),真正重要的论点是:需要设置为’attachment’而不是’inline’的disposition.
另一个参数:url_based_filename显然用于从URL确定文件的名称.由于我没有提供文件名,也许这是我提供给正在下载的文件的唯一方法,但我不确定.
我还需要将link_to标记更改为:
<%= link_to'下载文件',:action => ‘download_file’,:id => resource.id%>
请注意,提供具有当前资源的id的:id符号提供了识别相关资源所需的特定信息.
我希望这可以帮助其他人.这对其他人来说一定非常明显,因为我没有找到任何关于文件下载文件的基本教程.我还在学习很多东西.
更新:我不得不玩这个来获得理想的行为.以下是正在运行的新方法:
def download_file @resource = Resource.find(params[:id]) send_file(@resource.document.path,:url_based_filename => false) end
通过这些更改,我不再需要设置:type.设置“:url_based_filename => true”保持在URL中的记录ID之后命名文件.基于我对该参数的函数的读取,将此设置为false似乎是违反直觉的,但是,这样做会产生在实际文件名之后命名文件的期望结果.
我还使用了mime-types gem并将以下内容添加到我的video_uploader.rb文件中:
require 'carrierwave/processing/mime_types' class VideoUploader < CarrierWave::Uploader::Base include CarrierWave::MimeTypes process :set_content_type
这个gem显然设置了文件名中文件扩展名猜出的mime类型.这样做使得我不必在我的download_file方法中的send_file参数中设置:显式类型.