Bjoernsen Bjoernsen - 4 months ago 16
Ruby Question

Change tmp folder for uploaded files

All my uploaded files are temporary stored in the folder

/tmp
.

I would like to change this folder, because the
/tmp
folder is too small.
It does not help me to upload a file and after the upload to move it somewhere else.

I already tried to change
ENV['TMPDIR']
,
ENV['TMP']
, and
ENV['TEMP']
to something else, but my uploaded files (RackMultipart*) are still temporary stored in
/tmp
.

How can I change this behavior? Of course I could mount the
/tmp
to somewhere else, but it would be easier to tell Rails/Rack/Thin/Apache/... where to store the files. I am not using paperclip, etc.

For my server, I use Apache as a proxy balancer to pass the traffic to 4 thin server.

I have a Rails 4 rc1 project using ruby 2.0.

Edit:

def create
file = params[:sample_file][:files].first
md5_filename = Digest::MD5.hexdigest(file.original_filename)
samples = Sample.where("name in (?)", params["samples_#{md5_filename}"].map {|exp| exp.split(" (").first}) rescue []
file_kind = FileKind.find(params[:file_kind])

@sample_file = SampleFile.new
@sample_file.file_kind = file_kind
@sample_file.samples = samples
@sample_file.original_file_name = file.original_filename
@sample_file.uploaded_file = file #TODO: ..
@sample_file.user = current_user
...
#many other stuff
...

respond_to do |format|
if @sample_file.save
format.html {
render :json => [@sample_file.to_jq_upload].to_json,
:content_type => 'text/html',
:layout => false
}
format.json { render json: {files: [@sample_file.to_jq_upload]}, status: :created, location: @sample_file }
else
format.html { render action: 'new' }
format.json { render json: {files: [@sample_file.to_jq_upload]}.to_json, status: :ok}
end
end
end

Answer

If setting the TMPDIR,TMP,TEMP is not working, it could be that the directory you specified doesn't exist or is not writable. Or $SAFE variable is > 0. The tmp folder is determined using the function Dir.tmpdir (see http://www.ruby-doc.org/stdlib-1.9.3/libdoc/tmpdir/rdoc/Dir.html#method-c-tmpdir).

class Dir  
  def Dir::tmpdir
    tmp = '.'
    if $SAFE > 0
      tmp = @@systmpdir
    else
      for dir in [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp']
        if dir and stat = File.stat(dir) and stat.directory? and stat.writable?
          tmp = dir
          break
        end rescue nil
      end
      File.expand_path(tmp)
    end
  end
end

Ruby 2.1

def Dir::tmpdir
  if $SAFE > 0
    tmp = @@systmpdir
  else
    tmp = nil
    for dir in [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp', '.']
      next if !dir
      dir = File.expand_path(dir)
      if stat = File.stat(dir) and stat.directory? and stat.writable? and
          (!stat.world_writable? or stat.sticky?)
        tmp = dir
        break
      end rescue nil
    end
    raise ArgumentError, "could not find a temporary directory" if !tmp
    tmp
  end
end

So if you're setting the TMP env variables, make sure that the lines below are true

  1. $SAFE == 0
  2. File.stat("you_dir")
  3. File.stat("you_dir").directory?
  4. File.stat("you_dir").writable?

Another way to set tempdir is to override the tmpdir in your rails initializer, but obviously this bypasses any directory checking so u gotta make sure it exists/writable

class Dir
  def self.tmpdir
    "/your_directory/"
  end
end