GridFS是MongoDB提供的一种存储大文件的规范,文件在存储的过程中会分成一小块一小块(chunks),文件的信息会保存在另外一个集合中。
通过MD5校验过滤重复上传文件
在换乐网中,所有用户上传的文件都会保存在GridFS中:
通过MD5校验,不上传重复的文件,各种云盘上传文件时的秒传也是类似的功能。这样做的好处就是:服务器中的文件减少了,存储空间占用降低了,用户上传的速度加快了。
关键代码如下:
生成上传文件的MD5码:
Md5PasswordEncoder md5PasswordEncoder=new Md5PasswordEncoder(); String md5String="";try {MessageDigest md5Encoder = MessageDigest.getInstance("MD5"); byte[] digest = md5Encoder.digest(file.getBytes());md5String =new BigInteger(1, digest).toString(16);System.out.println(md5String);} catch (IOException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}
文件上传代码,上传之前会检验MD5码
/**保存文件到GirdFS,通过openUploadStream方式* @param bucket 容器名称* @param file 文件实体* @return 返回FileEntity*/public FileEntity save(FileEntity file){//检查是否之前已有人上传过该文件FileEntity filter = new FileEntity();filter.setMd5(file.getMd5());FileEntity result =this.find(filter);if(result!=null){file.setId(result.getId());return file;}//上传该文件gfsbk = GridFSBuckets.create(db, DEFAULT_BUCKET);GridFSUploadStream uploadStream = gfsbk.openUploadStream(file.getFileName());uploadStream.write(file.getContent());ObjectId id = uploadStream.getFileId();uploadStream.flush();uploadStream.close();file.setId(id);return file;}
从GridFS中获取图片显示在jsp页面中
因为MD5码可以标识一个文件,所以网站直接使用MD5码作为参数获取图片,先看下图片控制器:
@Controller
@RequestMapping("/files")
public class FileController {//TODO : 考虑安全问题,因为只要一个md5码就可以得到文件,是否会有漏洞?@Autowiredprivate GirdFSHelper girdFSHelper;@RequestMapping(method=RequestMethod.GET,path="/image/{key}")public void changeInfo(HttpServletResponse response,@PathVariable String key){FileEntity filter = new FileEntity();filter.setMd5(key);FileEntity file = girdFSHelper.download(filter);if(file==null){//TODO 显示一张默认图片}else{response.setContentType("image/*");try {response.getOutputStream().write(file.getContent());} catch (IOException e) {e.printStackTrace();}}}}
页面中<img>
的src可以这样写:
<img alt="" src="/files/image/9a3e601a54612f89ce6e97cd365a9c65">
如果直接打开这个链接,会下载一个文件,所以这个Controller直接再写一个方法就可以实现其它文件的下载。