`
tangzhibin
  • 浏览: 20459 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

mongodb系列之-mongodb gridfs分析(java应用)

阅读更多

 

Mongodb GridFS文件系统

 

Mongodb gridfs文件系统通过files与chunks 2个集合来保存文件,其中files集合保存每个文件的元数据(包括每个文件被分割成了多少)  ,

chunks集合具体保存每个文件相应的数据chunk,大于256kb的文件被分割为多个chunk,每个chunk最大保存256kb的数据(其实可以手动设置chunkSize,但貌似最大不能大于3M左右)

 

写文件:

  默认将整个文件拆为256Kb为单位的二进制字节数组——>再save到每个chunk中----->最后再保存files集合元数据

  java里面调用GridFSInputFile ifile=gridFS.createFile(f)方法会把db.fs.files集合中元数据各个参数初始化好,比如_id、chunkSize(默认256KB)、filename等

  写文件源码就不多分享了,挺简单的,大家可以去看源码,大致就是上面那个流程

 

读文件:

 

先看下2个集合的数据结构

switched to db category
hd1:PRIMARY> db.fs.files.findOne()
{
       "_id" : ObjectId("514ae50bf211487e93102dd3"),
       "chunkSize" : NumberLong(262144),  //每个chunk保存的数据大小(字节)
       "length" : NumberLong(1305),
       "md5" : "38ad64863784c3cb5d70a60d07e3bf23",//文件的md5校验值
       "filename" : "reference.xml",//文件名
       "contentType" : null,//文件类型
       "uploadDate" : ISODate("2013-03-21T10:46:35.863Z"),
       "aliases" : null
}
hd1:PRIMARY> db.fs.chunks.findOne()
{
       "_id" : ObjectId("514ae50bf211487e93102dd4"),
       "files_id" : ObjectId("514ae50bf211487e93102dd3"),//对应files集合中的_id
       "n" : 0,//第几个chunk
"data" : BinData(0,”...这里是二进制数据,省略n字”)
}

 

 

 Java里面查询:

 

 GridFS gridFS = new GridFS(db);        
BasicDBObject query = new BasicDBObject();
query.put("filename","reference.xml");
// 返回该文件对应的元数据信息
GridFSDBFile fs = gridFS.findOne(query);
// 将数据写入本地文件
fs.writeTo(new File("d:/reference.xml.xml"));
  

 

  

java源码剖析:

1:gridFS.findOne(query):

  
 public GridFSDBFile findOne( DBObject query ){
 //_filesCollection会在初始化GridFS类的构造函数中进行赋值,
//如:_filesCollection = _db.getCollection( _bucketName + ".files" );
   return _fix( _filesCollection.findOne( query ) );
  }

 

  

2:再看 fs.writeTo(...)方法:

 所有的writeTo方法最终都会去调用writeTo( OutputStream out )方法,接下来咱们就去看此方法的逻辑:

   

  public long writeTo( OutputStream out )
throws IOException {
//计算该文件的chunk数量
final int nc = numChunks();
for ( int i=0; i<nc; i++ ){
//正真去获取数据:获取每个chunk的二进制数据,并写入到out流
   out.write( getChunk( i ) );
}
return _length;
}

 

3:再看numChunks方法:

  public int numChunks(){
     //此处的的_length就是db.fs.files.findOne()结果中的length
     double d = _length;
  //然后与_chunkSize=262144注:(256k=262144字节)进行运算
     d = d / _chunkSize;
  //最后向上取整,这样就得到一个文件存了多少份chunk
     return (int)Math.ceil( d );
 }

 

 

4:再看getChunk()方法:

  byte[] getChunk( int i ){
     if ( _fs == null )
        throw new RuntimeException( "no gridfs!" );
       //获取具体的chunk上的数据,files_id对应该文件在files集合中的_id,n表示在第几个chunk上
  DBObject chunk = _fs._chunkCollection.findOne( BasicDBObjectBuilder.start( "files_id" , _id ).add( "n" , i ).get());
     if ( chunk == null )
          throw new MongoException( "can't find a chunk!  file id: " + _id + " chunk: " + i );
    
   return (byte[])chunk.get( "data" );
 }
 

 

这就是mongodb读取文件时候的相关流程

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics