Question: Question:
When deciding the file name of the file uploaded by the user, I came up with a method of issuing an ID from the current time (milliseconds) so that the file names do not conflict.
After trying various things, the following code was completed, but since I just converted the current time value to a 62-ary number, the first character of the file is fixed at almost p2 like "p2dhXa6" and "p2d9Wco".
You can leave it as it is, but is there a way to generate an ID that is unique, visually random, and has a shorter string length, using the characters available in the filename?
Current code
def uniqid()
def dec62(num)
table = [('0'..'9'),('a'..'z'),('A'..'Z')].map{|c| c.to_a }.flatten
num > 61 ? dec62(num/62)+table[num%62] : table[num%62]
end
dec62(Time.now.instance_eval { self.to_i * 1000 + (usec/1000) })
end
Answer: Answer:
SecureRandom
I think it's better to use SecureRandom. (I personally like SecureRandom.uuid
because it's easy to see that it was randomly generated.)
require "securerandom"
SecureRandom.hex
# => "3366ab379a65448704fa7c7cab4b0843"
SecureRandom.hex(32)
# => "4ab79521bf6712c1737b55f8393816b00996de29bed69257c5f6635bea899f9a"
SecureRandom.uuid
# => "d1d145ae-2e1e-4d5f-8f0b-e962c47624e0"
SecureRandom.urlsafe_base64
# => "B7Yj6QUYaYtbM7gflqEbaQ"
SecureRandom.urlsafe_base64(8)
# => "8CBbCIhp8hA"
URL-safe base64 (RFC 3548) is also "safe" as a file name because only "-" and "_" ("=" when padding is included) are used in addition to alphanumericals.
Tempfile
Tempfile is also a good choice for the purpose of creating temporary files. However, the directory is fixed. (The directory depends on the system.)
require "tempfile"
Tempfile.new("moemoe")
# => #<File:/var/folders/sz/slkk1lv965lcpl8djdlq8qdc0000gn/T/moemoe20150124-19905-m2sbfw>
Serial number
Also, if you want to create a unique file name for saving, you can use serial numbers. For example, if you are using Ruby on Rails (ActiveRecord), it is a good idea to create a file name based on the model id
. (To be precise, it may not be a serial number depending on the environment and operation contents, but it is guaranteed to be unique.)
class UserFile < ActiveRecord::Base
FILE_STORE_DIR = Rails.root + "store/user_files"
def filename
FILE_STORE_DIR + self.id.to_s
end
end
uf = UserFile.create
uf.filename
=> #<Pathname:/User/fate/rails/hoge/store/user_files/1>