解决重名问题的两种命名方法
md5加密
计算上传文件md5,以这个md5作为文件名称。这种方式出现重名,并且重名的文件是不一样的的几率由md5出现碰撞的几率决定。
使用md5重新命名的方法,有一个好处,就是上传同样的文件,服务器只会保存一份,不会浪费空间。这个方法的缺点也是比较明显的,就是md5名称看起来不是很友好,而且md5如果出现碰撞,就会导致数据丢失。现在md5的碰撞也逐渐被找到。效率还可以,600k的图片,大概20毫秒。足够了。
这种情况千万不要考虑删除文件,因为你永远不知道有多少用户在引用这个文件。
package sdibt.fight.util;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.MessageDigest;
import java.util.Date;
/**
* 任意数据都会生成128bit的摘要,转成16进制就是32位
* md5加密
* @author 111
*
*/
public class MD5Util {
/**
* byte数组转16进制字符串
* @param bytes
* @return
*/
public static String bytesToHex(byte[] bytes) {
StringBuilder stringBuilder = new StringBuilder();
int h;
for (byte b : bytes) {
//保持b由byte到int的二进制低8位的一致性,将高24位置0
/**
* 例如:byte-1的源码是100000001 补码是11111111,转int时jvm为了保存十进制的一致性对补码补1;
* int-1的补码是11...111(32个),所以转int后十进制值没变。但是二进制变了,如果直接转16进制是ffffffff,其实应该是ff;
* 所以为了保持二进制低8位的一致性,将高24置0
*/
if(b<0){
h=b&0xff;
}else{
h=b;
}
/**
* 一个byte=8bit,4bit为1个16进制数,所以一个10进制byte应该转为2个16进制数,不足16的补0
*/
if(h<16){
stringBuilder.append(0);
}
stringBuilder.append(Integer.toHexString(h));
}
return stringBuilder.toString();
}
/**
* 获得md5加密后的密文
* @param s 明文
* @return
*/
public static String getMD5(String s){
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] digest = md5.digest(s.getBytes("utf-8"));
s = bytesToHex(digest);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return s;
}
/**
* 计算文件内容的md5值
* @param filePath
* @return
* @throws Exception
*/
public static String getBigFileMD5(String filePath) throws Exception{
MessageDigest md5 = MessageDigest.getInstance("MD5");
FileChannel channel = FileChannel.open(Paths.get(filePath), StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
while(channel.read(buffer)!=-1){
buffer.flip();
md5.update(buffer);
buffer.clear();
}
return bytesToHex(md5.digest());
}
public static void main(String[] args) throws Exception {
}
}
以日期方式重命名
因为每个目录下的文件数量是有限制的,而且单个文件夹下的文件不宜过多,会影响检索速度,所以还要细分目录进行存储,通常用年月日来分目录,就是每天上传的文件保存到一个目录。把上面的格式稍微改一下,改成下面的格式:
2012/09/20/ 17 21 55 927386 . jpg
年/月/日/ 时 分 秒 微秒 后缀