生成唯一编号作为图像名称
本文关键字:图像 唯一 编号 | 更新日期: 2023-09-27 17:59:53
我是asp.net c#的初学者,开始开发一个网站,现在一直停留在图像上传表单上。我必须生成一个唯一的数字作为图像的名称,并将图像存储在图像文件夹中。如何使用c#在asp.net中生成超过2位数的唯一数字。唯一数字也可以包括字母。
非常感谢您的帮助。谢谢
正如germi所说,唯一的4位数将限制您只能获得10000张图像。如果你事先知道你永远不会有超过10000张图像,你可以从0开始,每次增加1来获得唯一的ID。
更好的解决方案是使用Guid。Guid是全局唯一的ID。
Guid g = Guid.NewGuid();
这样,您就不必担心实现和检查文件名是否唯一,因为它们保证是.
由于我通过评论询问是否可以包含字母,而您说"可以",因此这里有一个替代您已经接受的答案的选项。生成的图像名称发生冲突的几率要小得多。如果图像名称中只有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()时传递它。
我建议您不要使用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();
Guid
的设计是独一无二的,所以你在这方面不会有任何问题。
GUID是一个128位整数(16字节),可以在所有需要唯一标识符的计算机和网络中使用。这样的标识符被复制的概率非常低。
(请参阅文档)。
正如大家所说,4位数字非常小,除非在有限的用例中,否则不会特别有用。
您有几种可能的解决方案。使用Guid通常被认为是最好的解决方案,因为它适用于多台机器,您不必检查刚刚生成的Guid是否已经使用。所有其他方法都需要执行这种重复检查,这取决于名称的存储方式,可能是一件麻烦的事情。
如果正如你所说,你真的需要4位数字,而这就是你所允许的,那么随机数对你来说不是最好的。只需按顺序排列并使用关键部分。您可以在目录或数据库中查找第一次使用的最高值,然后开始递增一(您甚至可以使用Interlocked increment来增加数字)。
但是,正如其他人所说,你应该重新考虑4位数的限制。
你试过这样吗:
string filePath = Path.Combine(Server.MapPath("~/UserImages"), Path.GetFileName(Guid.NewGuid() + "_" + file.FileName));
以及你将要保存的这些路径。
我现在知道这是一个旧线程,但当我说为什么不,让我们使用Datetime ticks作为其他线程的替代时,我记得我自己。若要将图像名称存储在数据库中,则必须考虑字节。因此,与guid(没有破折号)相比:
long ticks = DateTime.Now.Ticks;
string tickUnique = String.Format("{0}", ticks);
string guidUnique = Guid.NewGuid().ToString();
guidUnique = guidUnique.Replace("-", "");
然后用于:
- tickUnique结果为:637483067615257804
- guidUnique结果为:72fdea88b6074595875d7a6240c390f1
最后一件事,我不得不提一下。日期时间刻度在同一线程中将始终是唯一的。在线程场景中,您必须小心谨慎。
编码快乐!
添加到此对话:
如果出于存储原因,你想保留一个真实的ID,但希望用户使用这些图像和/或以不同的方式生成文件名,你可以使用hashids.net等库。
基本上,你插入一个";盐";和一个数字,你会得到一个哈希,这个哈希可以被你的系统可逆(因为你知道salt!),但用户很难反转。这也可能有助于防止刮擦器扫描您的端点。
你的上传处理程序会看起来像这个
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.
}