它是mongodb的一个子模块,使用GridFS可以基于mongodb来持久存储文件.并且支持分布式应用(文件分布存储和读取).GridFS是mongodb中用户存储大对象的工具,对于mongodb,BSON格式的数据(文档)存储有尺寸限制,最大为16M.但是在实际系统开发中,经常会有上传图片或者文件的功能,这些文件可能尺寸会很大..我们可以借用Gridfs来辅助实现这些文件的管理.
Mongo GFS的文件表是由表名.files和表名.chunks构成,前者是文件信息构成,后者是文件的内容,两者通过_id与files_id建立关联。
GridFS会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为mongodb的一个文档(document)被存储在chunks集合中..gridfs模块会为每个文件创建chunks和files信息.每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中.files集合中的文档就是BSON格式,可以使用mongodb的索引等等特性,当然可以对files文档做数据分析。
使用场景:如果你的系统有如下情景
1) 有大量的上传图片(用户上传或者系统本身的文件发布等)
2) 文件的量级处于飞速增长,有可能打到单机操作系统自己的文件系统的查询性能瓶颈,甚至超过单机硬盘的扩容范围.
3) 文件的备份(不适用gridfs这种三方也可以做,但是不尽方便),文件系统访问的故障转移和修复..
4) 文件的索引,存储除文件本身以外还需要关联更多的元数据信息(比如,不仅仅存储文件,还要保存一些文件的发布式作者/发布时间/文件tag属性等等自定义信息)并且需要索引的...
5) 基于4),对文件的分类模糊,如果采用操作系统的文件系统,文件夹分类关系混乱或者无法分类时..
6) 当前系统是基于web的,对图片的访问根据url了规则路由的..(普通文件系统也可以)
7) 文件尺寸较小,而且众多,且文件有可能被迁移/删除等..
这次系统中的图片全部上传到了mongodb中,其中servlet代码如下。
Mongodb不是提前建好表的,即不是关系型数据库,mongodb的表是在代码中建立的。详细代码如下。
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
WebApplicationContext wac = (WebApplicationContext) request
.getSession()
.getServletContext()
.getAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
MongoDBManager mongoDBManager = (MongoDBManager) wac.getBean("mongoDBManager");
String industryId=request.getParameter("industryId");
DB buildingLayoutDB = null;
GridFS gridFS = null;
buildingLayoutDB = mongoDBManager.getDB("industrysurvey"); // 数据库名称
gridFS = new GridFS(buildingLayoutDB,"aptitude");//获取一个gridFS的对象
GridFSFile file=null;
Date date=new Date();
int pot = 0;
FileRenamePolicy rfrp=new RandomFileRenamePolicy();
MultipartParser mp = new MultipartParser(request, 1024 * 1024 * 1024,true,true,"utf-8");
ObjectId fileId=null;
String filename = null;
FilePart filePart = null;
Part part = null;
while ((part = mp.readNextPart()) != null) {
if (part.isFile()) {// it's a file part
filePart = (FilePart) part;
String fileName = filePart.getFileName();
// 设置文件更名器
filePart.setRenamePolicy(rfrp);
if (fileName != null) {// the part actually contained a file
filename=filePart.getFileName();
pot=filename.lastIndexOf(".");
if(pot!=-1){
}
}
filename = filePart.getFileName();
InputStream in = filePart.getInputStream(); ;
file = gridFS.createFile(in);//创建gridfs文件
file.put("filename", industryId);
file.put("uploadDate", date);
file.put("contentType",filename.substring(pot));
file.put("viewName",filename);
file.save();
fileId = (ObjectId) file.getId();
// System.out.println(fileId);
} else {// the field did not contain a file
// logger.debug("file: name=" + name + "; EMPTY");
}
}
//修改原数据库中的FileId
IndustryServiceImpl industryService= (IndustryServiceImpl) wac.getBean("industryService");
IIndustry iIndustry = industryService.getById(industryId);
IndustryForm form = new IndustryForm();
form.setAbbreviation(iIndustry.getAbbreviation());
form.setAddress(iIndustry.getAddress());
form.setFullName(iIndustry.getFullName());
form.setLegal(iIndustry.getLegal());
form.setMail(iIndustry.getMail());
form.setNature(iIndustry.getNature());
form.setOrgCode(iIndustry.getOrgCode());
form.setPhone(iIndustry.getPhone());
form.setQC(iIndustry.getQC());
form.setResume(iIndustry.getResume());
form.setState(iIndustry.getState());
form.setType(iIndustry.getType());
form.setZipCode(iIndustry.getZipCode());
form.setLegalPost(iIndustry.getLegalPost());
form.setLegalPhone(iIndustry.getLegalPhone());
form.setLegalMobilPhone(iIndustry.getLegalMobilPhone());
form.setFile_licenseId(iIndustry.getFile_licenseId());
System.out.println(fileId.toString());
form.setFile_QcId(fileId.toString());
industryService.modify(industryId, form);
//System.out.println("更新数据库啦!!!");
response.getWriter().print(file);
}
在上传到mongodb后,保存mongodb中主id到oracle相应的表中。这样将图片等不重要的大文件上传到mongodb中,节省了时间,提高了效率。相应的图片存取也变得容易简单。