换乐网GridFS应用分析

GridFS是MongoDB提供的一种存储大文件的规范,文件在存储的过程中会分成一小块一小块(chunks),文件的信息会保存在另外一个集合中。

通过MD5校验过滤重复上传文件

在换乐网中,所有用户上传的文件都会保存在GridFS中:

Created with Raphaël 2.1.0 开始 获得上传的文件 生成文件的MD5码 GridFS中有该MD5码? 不上传,返回GridFS中文件ID 结束 上传文件,返回GridFS中文件ID yes no

通过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码就可以得到文件,是否会有漏洞?

    @Autowired
    private 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直接再写一个方法就可以实现其它文件的下载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值