随笔-69  评论-645  文章-19  trackbacks-13

网上流行的多文件上传,都是上传之后,用日期时间命名。都认为方便、简单,似乎还能避免同目录下产生相同的文件。
代码大多如下:

string 新文件名 = DateTime.Now.ToString("yyMMddHHmmss");

上面这行代码会导致很有趣的bug:那就是当网站繁忙很多人同时上传的时候,或者一个人多文件同时上传的时候,你会发现,你传上去文件,经常性(跟别人)都是一样的,经常性“丢掉”一些图片。

你会奇怪,为什么?

很简单,服务器处理太快了,几乎1秒内就处理你的多文件上传请求,这一秒内,所有的文件名都相同(因为上面那个行代码就只精确到秒)。

OK,既然是文件名相同,我精确到毫秒,不就解决了?于是有了下面的代码:
string 新文件名 = DateTime.Now.ToString("yyMMddHHmmssfff");//精确到毫秒,防止1秒内被处理的文件获得的新名称都相同
经过上面的改造,会发现问题减少了很多,不再经常“丢”图片了……但是,偶尔还是有照片丢失的情况发生……

知道原因吗?MSDN告诉我们:“Windows系统时钟精确到10~15毫秒”,也即说,DateTime类型只能精确到10~15毫秒。如果用时间命名,即便精确到毫秒,10~15毫秒内处理的文件,名字仍然会相同,有趣的bug仍然会产生。

故,不推荐使用日期时间命名文件。

那怎么办呢?用Guid!唯一的、一出生即与众不同的家伙,它的唯一性,理论上保证了同一目录下无可能出现重复的文件名。
string 新文件名 = Guid.NewGuid().ToString("N");

posted on 2008-05-14 10:20 Kai.Ma 阅读(1091) 评论(22)  编辑 收藏 所属分类: Net 2.0 & ASP.NET & AJAX

评论:
#1楼  2008-05-14 10:27 | 金色海洋(jyk)      
有些情况,我会把登录人的ID加在文件名的后面。
  回复  引用  查看    
#2楼  2008-05-14 10:28 | Howard Queen      
时戳能知道文档大致生成时间,对日后清理可能有好处;冲突的问题可以通过lock解决,我觉得不会损失多少性能。但guid确实似乎挺通用。
  回复  引用  查看    
#3楼  2008-05-14 10:29 | icecool [未注册用户]
用下Thread.sleep() 也是可以的
  回复  引用    
#4楼  2008-05-14 10:32 | yongfa365.com [未注册用户]
不错,唯一缺点就是看不到这图片什么时候发的。
  回复  引用    
#5楼  2008-05-14 10:33 | 11145623465234534 [未注册用户]
日期+ID+图片大小,可以防止重复上传图片,又避免重复上传
  回复  引用    
#6楼  2008-05-14 10:34 | MicroYee      
后面可加几位随机数也行
  回复  引用  查看    
#7楼 [楼主] 2008-05-14 10:39 | Kai.Ma      
@yongfa365.com
可以给文件加一个日期时间的文件夹嘛,一般精确到小时即可。一小时生成一个文件夹。就可以大致看出该文件什么时候生成的了。

要再精确可以看文件属性。
  回复  引用  查看    
#8楼 [楼主] 2008-05-14 10:40 | Kai.Ma      
@MicroYee
随机数一样会出现重复的可能。我试验过,尤其是网站繁忙的时候
  回复  引用  查看    
#9楼  2008-05-14 10:52 | ladyloveme      
我一般是 文件名=DateTime.Now.ToString("yyMMddHHmmssfff")+"_"+三位随机数
  回复  引用  查看    
#10楼  2008-05-14 11:25 | rudolph      
我的是按照日期来建立文件夹,文件名用Guid
  回复  引用  查看    
#11楼  2008-05-14 11:34 | WEBBER      
这也放首页??
  回复  引用  查看    
#12楼  2008-05-14 11:40 | simon4545真名 [未注册用户]
我晕,我当时什么呢,后面用个随机rand码就行呀加上时间,用guid也行,不过就是不能从图片中知道是什么时候加入的。
这个放在首页夸张了点吧
  回复  引用    
#13楼  2008-05-14 11:42 | SZW      
突然有个想法,既然用了Guid,这个Guid是不是也可以用图片文件MD5编码,为了排序也可以在前面加个日期或ID之类的。这样可以很快找出内容相同的图片(如果有这样的需求的话,当然这个方法用在别的文件上可能用处更大一点,比如文档、存档等等)
  回复  引用  查看    
#14楼  2008-05-14 11:44 | tthxnz      
DateTime.Ticks//我就不相信还有重复
  回复  引用  查看    
#15楼  2008-05-14 11:59 | ASP.NET CMS [未注册用户]
加线程锁啊
lock一下就可以了
  回复  引用    
#16楼  2008-05-14 12:10 | kerry jiang [未注册用户]
这个话题,私下偷讨论讨论也就够了
  回复  引用    
#17楼 [楼主] 2008-05-14 12:15 | Kai.Ma      
@SZW
是的,想法可以。
MD5处理图片,会不会消耗太大了?尤其是对于高访问的服务器。
  回复  引用  查看    
#18楼  2008-05-14 12:33 | SZW      
@Kai.Ma
还好的,文件的MD5编码主要是根据文件类型、创建时间、内容等为依据生成的,我以前单机上做过生成文件MD5编码,花的时间可以忽略不计。毕竟你服务器也不会一天到晚不停上传吧,上传几个文件就运算几次,生成了文件名就ok了。
  回复  引用  查看    
#19楼 [楼主] 2008-05-14 13:17 | Kai.Ma      
@tthxnz
这个理论上还是可能有重复的。DateTime类型在windows(xp,2003,vista)上只能精确到10~15毫秒。
--引用--------------------------------------------------
DateTime.Ticks//我就不相信还有重复

--------------------------------------------------------

  回复  引用  查看    
#20楼  2008-05-14 13:53 | 拒绝潜水的鱼      
并发处理问题了
  回复  引用  查看    
#21楼  2008-06-06 20:02 | 菜菜灰      
时间+guid
  回复  引用  查看    
#22楼  2008-10-05 07:01 | 飞林沙      
恩 个人认为用GUID比较合适
如果需要的话 可以用时间来做个第二层的索引
  回复  引用  查看    

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-05-14 12:14 编辑过
"五向定位"职业成长路线公开课(上海、南京、大连)
Google站内搜索


相关链接: