我应该将图像放在heroku rails应用程序中?

时间:2014-04-04 22:03:14

标签: ruby-on-rails heroku

我有一个iOS api链接到rails应用程序。我已经向rails app发送了一个iOS图像,我试图将其存储为header_img,但是我收到的错误是他们没有公共目录。在我的heroku api中为图像指定的好路径是什么?

这是heroku错误:

2014-04-04T21:51:47.179916+00:00 app[web.1]: 
2014-04-04T21:51:47.179916+00:00 app[web.1]: Errno::EISDIR (Is a directory - public/header_img/):
2014-04-04T21:51:47.179916+00:00 app[web.1]:   app/controllers/groups_controller.rb:98:in `initialize'
2014-04-04T21:51:47.179916+00:00 app[web.1]:   app/controllers/groups_controller.rb:98:in `open'
2014-04-04T21:51:47.179916+00:00 app[web.1]:   app/controllers/groups_controller.rb:98:in `upload_header_img'
2014-04-04T21:51:47.179916+00:00 app[web.1]:   app/controllers/groups_controller.rb:44:in `create'

这是我的群组控制器:

class GroupsController < ApplicationController
  # GET /groups
  # GET /groups.json

  before_filter :require_auth

  def index
    @privategroups = @user.groups
    @publicgroups = @user.followees(Group)

    @groups = (@privategroups + @publicgroups).sort_by( &:created_at ).reverse
  end

  # GET /groups/1
  # GET /groups/1.json
  def show
    @group = Group.find(params[:id])
    @posts = @group.posts
  end

  # GET /groups/new
  # GET /groups/new.json
  def new
    @group = Group.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @group }
    end
  end

  # GET /groups/1/edit
  def edit
    @group = Group.find(params[:id])
  end

  # POST /groups
  # POST /groups.json
  def create
    @group = Group.new(params[:group])
    @group.owner_id = @user.id
    header_img = @group.header_img || @group.decode_header_img_data
    if header_img.present?
      upload_header_img(header_img)
    end

    respond_to do |format|
      if @group.save
        @membership = @user.memberships.build(group_id: @group.id)
        @membership.save
        format.html { redirect_to @group, notice: 'Group was successfully created.' }
        format.json { render json: @group, status: :created, location: @group }
      else
        format.html { render action: "new" }
        format.json { render json: @group.errors, status: :unprocessable_entity }
      end
    end
  end

  # PUT /groups/1
  # PUT /groups/1.json
  def update
    @group = Group.find(params[:id])

    respond_to do |format|
      if @group.update_attributes(params[:group])
        format.html { redirect_to @group, notice: 'Group was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @group.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /groups/1
  # DELETE /groups/1.json
  def destroy
    @group = Group.find(params[:id])
    @group.destroy

    respond_to do |format|
      format.html { redirect_to groups_url }
      format.json { head :no_content }
    end
  end

  private  
   def upload_header_img(header_img_io)           
      # upload to the exact location account id and extension
      extension = File.extname(header_img_io.original_filename)
      # rails take public as root directory
      # under the root directory (public)
      # there are a icon directory
      header_img_url = "/header_img/"+@group.id.to_s + extension

      # open in binary mode
      File.open("public"+header_img_url,'wb') do |file|
      file.write(header_img_io.read)
      end

      @group.update_attribute(:header_img_url, header_img_url)
   end
end

1 个答案:

答案 0 :(得分:1)

虽然我无法提供直接的答案,但我有一些可能会有所帮助的想法:


According to Heroku,他们运行只读文件系统:

  

您的应用程序被编译成一个slug,以便由dyno快速分发   经理。 slug的文件系统是只读的,这意味着你   无法动态写入文件系统进行半永久存储。   不支持以下类型的行为:

     
      
  • 在公共目录中缓存页面
  •   
  • 将上传的资源保存到本地   磁盘(例如,使用attachment_fu或paperclip)
  •   
  • 撰写全文索引   与Ferret写入文件系统数据库,如SQLite或GDBM
  •   
  • 访问git-wiki等应用程序的git repo
  •   

<强> CORRECTION

从那以后发现上面是Bamboo堆栈(旧)。 cedar stack (new) supports temporary file writing

  

每个dyno都有自己的短暂文件系统,并带有新的副本   最近部署的代码。在dyno的一生中它的运行   进程可以使用文件系统作为临时暂存器,但没有   写入的文件对任何其他dyno和中的进程可见   写入的任何文件将在dyno停止时丢弃   重新启动。

我们使用Paperclip&amp;上传到Heroku(在测试时),通常不支持每次重新部署应用时都会覆盖任何文件


<强>存储

ChrisBarthol提出了一个很好的建议 - 将所有user-submitted资产存储在S3或其他第三方系统上。我会更进一步说你可能会因使用Paperclip保存文件而受益匪浅:

#app/models/group.rb
Class Group < ActiveRecord::Base
    has_attached_file :header_img
       :storage => :s3,
       :s3_credentials => Proc.new{|a| a.instance.s3_credentials }

    validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/   
end