13

私が取り組んでいる Ruby on Rails アプリでは、ユーザーがファイルをアップロードできるようにし、これらのファイルに短いランダムな英数字の名前を付けたいと考えています。(例: 'g7jf8' または '3bp76')。これを行う最善の方法は何ですか?

元のファイル名とタイムスタンプからハッシュ/暗号化された文字列を生成することを考えています。次に、データベースにクエリを実行して、データベースが存在しないことを再確認します。存在する場合は、別のものを生成して繰り返します。

このアプローチで見られる問題は、文字列が重複する可能性が高い場合、データベースの負荷がかなり増加する可能性があることです。

4

7 に答える 7

12

私はこれを使用します:)

def generate_token(column, length = 64)
  begin
    self[column] = SecureRandom.urlsafe_base64 length
  end while Model.exists?(column => self[column])
end

Modelモデル名に置き換えてください

于 2013-03-17T13:40:05.300 に答える
10
SecureRandom.uuid

グローバルに一意の文字列を提供します。http://en.m.wikipedia.org/wiki/Universally_unique_identifier

SecureRandom.hex 32

ランダムな文字列を返しますが、そのアルゴリズムは一意性のために最適化されていません。もちろん、真のランダム性を仮定すると、32 桁との衝突の可能性は基本的に理論上のものです。100 年間で 1 秒あたり 10 億を稼ぐことができ、衝突の可能性は 50% しかありません。

于 2013-03-17T10:23:38.530 に答える
6

Ruby のSecureRandom.hex関数を、生成したい任意の文字数で使用します。

于 2013-03-17T09:11:42.767 に答える
0

実際には一意のファイル名が必要なようですよね?複雑なソリューションを忘れて、Time#nsecを使用してみませんか?

t = Time.now        #=> 2007-11-17 15:18:03 +0900
"%10.9f" % t.to_f   #=> "1195280283.536151409"
于 2013-03-17T10:49:12.247 に答える
0

16進数または数値のダイジェストを生成することになった場合は、数値をたとえばBase 62として表すことで、コードを短くすることができます。

# This is a lightweight base62 encoding for Ruby integers.
B62CHARS = ('0'..'9').to_a + ('a'..'z').to_a + ('A'..'Z').to_a

def base62_string nbr
  b62 = ''
  while nbr > 0
    b62 << B62CHARS[nbr % 62]
    nbr /= 62
  end
  b62.reverse
end

使用する文字セットを制限することが重要な場合(たとえば、ファイル名に大文字が含まれていない場合)、適切な乱数を入力する方法を見つけることができれば、このコードを簡単に適合させることができます。

ファイル名が半安全であると想定される場合は、ストレージ内に実際の名前よりも多くの可能な名前があるように調整する必要があります。

于 2013-03-17T09:22:10.870 に答える
0

新しいファイルが追加されるたびに増分することで一意の ID を割り当て、OpenSSL::Cipherどこかに保存した定数キーを使用してその ID を暗号化された文字列に変換できます。

于 2013-03-17T09:16:13.077 に答える