我们的个别系统里面会经常遇到一些小型的图片(小于1.5MB),目前大多数的解决方案是:这些图片如果放在服务器的文件硬盘里,然后链接放在关系型数据或者类似mongodb的nosql数据库里。
但是不得不提出一个问题是。比如学校,政务机关的系统,经常会上传一些证件照,这些图片也不大,但是量很多。如果要删除时候,或者逻辑删除时候,就会出现一系列的问题。
物理删除:图片地址的库数据删掉,然后服务器文件磁盘上的文件要删掉,要执行两次操作,很繁琐。大多数的系统是直接删除地址库里的地址,服务器文件磁盘上的文件不删除。随着时间推移,服务器磁盘容量将逐渐被这些无人管的图片占光,就类似于那种野指针情况类似(这种情况属于慢性的。野指针直接占用RAM资源,或者指向别的地方,可能会造成服务器瘫痪)
那么需要一个简单,成本低廉适合这种小系统的文件服务器,mongodb不适用gridfs,直接存储小型图片是再好不过了。
我针对这些问题写了一个小demo,希望能够达到抛砖引玉的效果,同时demo源码免费无限次下载。
controller里的方法接收文件形参加上注解
@RequestParam("file") MultipartFile file
文件的内容,使用二进制的类型来接收和存放
private Binary content; // 文件内容
File的实体类型
public File(String name, String contentType, long size, Binary content) {
this.name = name;
this.contentType = contentType;
this.size = size;
this.uploadDate = new Date();
this.content = content;
}
controller接收文件的处理,mongodb是最接近关系型库的nosql,存放里将这些小文件转换成二进制数据存放。再对文件的名称添加查询索引,那么查询的时候这些小文件就像查询一条数据一样的优雅。更加开心的是还可以运用一些mongodb的新特性来操作这些小文件。
File f = new File(file.getOriginalFilename(), file.getContentType(), file.getSize(),
new Binary(file.getBytes()));
存放和读取文件的dao
//存放图片
mongoTemplate.save(file);
//获取图片
log.info(" " );
Query query = new Query();
if(StringUtils.isNotBlank(_id)) {
query.addCriteria(Criteria.where("_id").is(new ObjectId(_id)));
}
return mongoTemplate.findOne(query, File.class);
controller返回图片时
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; fileName=" + new String(file.getName().getBytes("utf-8"),"ISO-8859-1"))
.header(HttpHeaders.CONTENT_TYPE, "application/octet-stream")
.header(HttpHeaders.CONTENT_LENGTH, file.getSize() + "").header("Connection", "close")
.body(file.getContent().getData());
源码下载地址:https://gitee.com/cnhellorui/some_source_code/tree/master/mongo_file_server
如果感觉好的话,欢迎follow and star me,谢谢!如果有错误和需要改进的地方 email me:chenrui@marsdl.com