Rails为paperclip上传文件添加访问控制

0 前言

由paperclip上传的文件默认是放在rails项目的public目录下的,也就是说,只要能得到该文件的URL,就可以直接访问/下载该文件,如果要对该文件添加访问控制,就需要更改paperclip的默认上传位置。

1 更改paperclip默认的上传位置

若有一个story类,每个story有一个封面cover,该cover是一张图片,就可以这样更改model定义:

class Story < ActiveRecord::Base
  has_attached_file :cover,
  :styles=>{:small=>"32x32"}, 
  :path => ":rails_root/paperclip/:class/:attachment/:id/:style/:filename",
  :url => "/paperclip/:class/:attachment/:id/:style/:filename"
end

要同时修改path和url,url是相对于rails工程而言,被rails app用来获取图片渲染页面;而path是相对于rails app服务器而言,在整个宿主文件系统中的路径。必须同时修改path和url。

这里,将保存paperclip的上传文件的目录设置为rails工程根目录下的paperclip目录。

2 添加controller

在routes.rb中添加路由:

get "/paperclip/:class/:attachment/:id/:style/:filename",to:"assets#show"

添加assets_controller.rb文件:

class AssetsController < ApplicationController
  def show
    cls=params[:class].singularize.capitalize.constantize
    asset=cls.find params[:id]
    send_file asset.send(params[:attachment].singularize).path(params[:style])
  end
end

在提交的参数中params[:class]是复数形式,而通常类定义都是单数如Story,params[:attachment]是也复数形式而类定义中cover为单数,所以都要将他们变成单数,如果类中定义的attachment是复数形式,那么这里attachment就不必转换为单数,否则会引发NoMethod异常。

现在,所有的paperclip资源都由AssetsController控制,所以在其中添加诸如身份登录验证等before_filter就很方便了。在加入身份验证后,即便用户得到该cover的URL,在未登录的情况下,也无法直接访问该图片了。

Comments