【问题标题】:Generate unique number as image name生成唯一编号作为图像名称
【发布时间】:2014-04-23 13:57:06
【问题描述】:

我是asp.net c#的初学者,开始开发一个网站,现在卡在图片上传表单上。我必须生成一个唯一编号作为图像名称并将图像存储在图像文件夹中。如何使用 c# 在 asp.net 中生成超过 2 位的唯一编号。唯一编号也可以包含字母。

非常感谢任何帮助。 谢谢!

【问题讨论】:

  • unique number of 4 digits?祝你好运。你意识到你只会得到10000个,对吧?我建议您为此使用 Guid 之类的东西。
  • 如果您将拥有超过 10000 张图片,它们如何才能独一无二?
  • 只使用 Guid,而不是整数。 myImage.ID = Guid.NewGuid() 保证在这个宇宙中是随机的
  • 可以包含字母吗?
  • 建议一些替代的想法。在我的情况下,它是一个网站,用户不会存储超过 100 张图片。我只是允许用户动态上传他的画廊的图片。

标签: c# asp.net


【解决方案1】:

正如 Germi 所说,唯一的 4 位数字会将您限制为仅 10000 张图像。如果您事先知道,您永远不会拥有超过 10000 张图像,您可以从 0 开始,每次将数字增加 1 以获得唯一 ID。

更好的解决方案是使用 Guid。 Guid 是全球唯一的 ID。

Guid g = Guid.NewGuid();

那么您就不必担心实现和检查您的文件名是否是唯一的,因为它们保证是唯一的。

【讨论】:

    【解决方案2】:

    由于我通过评论询问是否可以包含字母并且您说“是”,因此这是您已经接受的答案的替代方案。您生成的图像名称相互冲突的机会要小得多。如果图像名称中只有 1 个数字或字母(小写或大写),则奇数为 1/(10 + 26 + 26)。如果图像名称中有 n 个数字或字母(小写或大写),则奇数会小得多。实际上是 (1/62) ^ n。 (^ 的幂)。无论如何,这是代码:

     public char GenerateChar(System.Random random)
     {
            char randomChar;
            int next = random.Next(0, 62);
            if (next < 10)
            {
                randomChar = (char) (next + '0'); //0, 1, 2 ... 9
            }
            else if (next < 36)
            {
                randomChar = (char) (next - 10 + 'A'); //A, B, C ... Z
            }
            else
            {
                randomChar = (char) (next - 36 + 'a'); //a, b, c ... z
            }
            return randomChar;
    }
    
    public string GenerateString(System.Random random, int length)
    {
            char[] randomStr = new char[length];
            for (int i = 0; i < length; i++)
            {
                randomStr[i] = GenerateChar(random);
            }
            return new string(randomStr);
    }
    

    正如一些人指出的那样,只需调用一次 new Random() 或将其设为静态或类似的东西,然后在每次调用 GenerateString() 时将其传递。

    【讨论】:

      【解决方案3】:

      我建议您不要为此使用 4 位数字,因为您只会得到其中的 10000 个。看看Guid - 它旨在为您提供独特的价值。

      如果数字不必是随机的,您可以每次将计数器加一并跟踪它。

      如果你真的打算使用 0-10000 的随机数,你可以使用这样的东西:

      Random r = new Random(); // <-- this should be only called once and not every time you want a random number
      int nextRandom = r.Next(10000);
      // as per the updated question, you want at least two digits
      int nextRandomTwoDigits = r.Next(9990) + 10;
      

      在此之后,您必须检查该图像是否已经存在(或者您必须保留一个已使用数字的列表并在那里查看)。

      如果你想使用Guids,你可以这样做:

      Guid newGuid = Guid.NewGuid();
      string imageName = newGuid.ToString();
      

      Guids 的设计是独一无二的,因此您在这方面不会有任何问题。

      GUID 是一个 128 位整数(16 个字节),可以在需要唯一标识符的所有计算机和网络中使用。这样的标识符被复制的概率非常低。

      (见documentation)。

      【讨论】:

      • 为什么要使用Random?我会简单地在循环中将值增加 1 并检查是否已经存在具有该名称的文件。如果没有,请打破循环。
      • @TimSchmelter:你是对的。对我来说,“独特”总是触发“随机”的本能。只是加一更容易。
      • @TimSchmelter 正在使用随机解决问题的更好方法。
      • @inox:这是一个不同的要求。如果您需要随机数,请使用Random,如果您不需要随机数,请使用简单的计数器。顺便说一句,如果需要,您可以使用前导零格式化字符串:num.ToString("d4");(f.e. 0008)。见:msdn.microsoft.com/en-us/library/vstudio/…
      【解决方案4】:

      正如大家所说,4 位数字非常小,除非在有限的用例中,否则并不是特别有用。

      您有几种可能的解决方案。使用 Guid 通常被认为是最好的解决方案,因为它可以跨机器工作,您不必检查刚刚生成的是否已被使用。所有其他方法都需要执行此重复检查,这取决于名称的存储方式。

      如果如您所说,您确实需要 4 位数字,而这就是您所允许的全部,那么随机数并不适合您。只需按顺序进行并使用关键部分。您可以在目录或数据库中查看第一次使用的最高值,然后以 1 开始递增(您甚至可以使用 Interlocked Increment 来增加数字)。

      但是,正如其他人所说,您应该重新考虑 4 位数的限制。

      【讨论】:

      • 谢谢。你的解释很完美。
      【解决方案5】:

      你有没有这样尝试过:

       string filePath = Path.Combine(Server.MapPath("~/UserImages"), Path.GetFileName(Guid.NewGuid() + "_" + file.FileName));
      

      你将保存这些路径。

      【讨论】:

      • 在这种情况下,我是否需要一个名为 UserImages 的文件夹。
      • 是的..您需要文件夹,但您必须根据需要更改文件夹名称
      • 每张图片都保存在这个文件夹中,并带有一个唯一的ID。
      • 你能告诉我任何检查随机 id 可用性并将图像保存在具有有效 id 的文件夹中的示例代码吗?
      • Guid.NewID() 是每次生成的随机数,并且是唯一的
      【解决方案6】:

      我现在这是一个旧线程,但当我说为什么不时我记得我自己,让我们使用日期时间刻度作为其他任何东西的替代品。 如果您将图像名称存储在数据库中,那么您必须考虑字节。 所以与 guid(没有破折号)相比:

       long ticks = DateTime.Now.Ticks;
       string tickUnique = String.Format("{0}", ticks);
       string guidUnique = Guid.NewGuid().ToString();
       guidUnique = guidUnique.Replace("-", "");
      

      那么为:

      1. 勾选唯一的结果是:637483067615257804
      2. guidUnique 结果为:72fdea88b6074595875d7a6240c390f1

      最后一点,我不得不提一下。 在同一线程中,日期时间刻度将始终是唯一的。在线程场景中您必须小心。

      编码愉快!

      【讨论】:

        【解决方案7】:

        要添加到此对话中:

        如果您出于存储原因想要保留真实 ID,但希望您的用户使用这些图像和/或生成不同的文件名,您可以使用诸如 hashids.net 之类的库。

        基本上,您插入一个“盐”和一个数字,您就会得到一个系统可以逆转的哈希(因为您会知道盐!)但用户很难逆转。这也可以帮助您防止爬虫扫描您的端点。

        您的上传处理程序将如下所示

        
        private readonly IHashids _hashidsSource = new Hashids("Salty salt");
        
        async Task HandleUploadedImage(MyImage img, CancellationToken ct)
        {
            // Assuming MyImage.Id is an int autogenerated by each uploaded image.
            var hashedFilename = _hashidsSource.Encode(img.Id);
            img.Filename = hashedFilename;
            // TODO: ???
            // Profit.
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-05-21
          • 1970-01-01
          • 2017-04-06
          • 1970-01-01
          • 1970-01-01
          • 2012-04-14
          • 1970-01-01
          • 2011-07-02
          相关资源
          最近更新 更多