me.lightspeed7.mongofs.gridfs.GridFS Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mongoFS Show documentation
Show all versions of mongoFS Show documentation
An extension to the MongoDB Java Driver library that goes beyond what the GridFS feature supports.
Compressed file storage, zip files, temporary files
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package me.lightspeed7.mongofs.gridfs;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.lightspeed7.mongofs.InputFile;
import org.bson.types.ObjectId;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
/**
* Implementation of GridFS - a specification for storing and retrieving files that exceed the BSON-document size limit of 16MB.
*
* Instead of storing a file in a single document, GridFS divides a file into parts, or chunks, and stores each of those chunks as a
* separate document. By default GridFS limits chunk size to 256k. GridFS uses two collections to store files. One collection stores the
* file chunks, and the other stores file metadata.
*
* When you query a GridFS store for a file, the driver or client will reassemble the chunks as needed. You can perform range queries on
* files stored through GridFS. You also can access information from arbitrary sections of files, which allows you to "skip" into the middle
* of a video or audio file.
*
* GridFS is useful not only for storing files that exceed 16MB but also for storing any files for which you want access without having to
* load the entire file into memory. For more information on the indications of GridFS, see MongoDB official documentation.
*
*/
public class GridFS {
/**
* File's chunk size
*/
public static final int DEFAULT_CHUNKSIZE = 255 * 1024;
/**
* Bucket to use for the collection namespaces
*/
public static final String DEFAULT_BUCKET = "fs";
/**
* File's max chunk size
*
* @deprecated You can calculate max chunkSize with a similar formula {@link com.mongodb.MongoClient#getMaxBsonObjectSize()} - 500*1000.
* Please ensure that you left enough space for metadata (500kb is enough).
*/
@Deprecated
public static final long MAX_CHUNKSIZE = (long) (3.5 * 1000 * 1000);
private final DB database;
private final String bucketName;
private final DBCollection filesCollection;
private final DBCollection chunksCollection;
/**
* Creates a GridFS instance for the default bucket "fs" in the given database. Set the preferred WriteConcern on the give DB with
* DB.setWriteConcern
*
* @param db
* database to work with
* @throws com.mongodb.MongoException
* @see com.mongodb.WriteConcern
*/
public GridFS(final DB db) {
this(db, DEFAULT_BUCKET);
}
/**
* Creates a GridFS instance for the specified bucket in the given database. Set the preferred WriteConcern on the give DB with
* DB.setWriteConcern
*
* @param db
* database to work with
* @param bucket
* bucket to use in the given database
* @throws com.mongodb.MongoException
* @see com.mongodb.WriteConcern
*/
public GridFS(final DB db, final String bucket) {
this.database = db;
this.bucketName = bucket;
this.filesCollection = database.getCollection(bucketName + ".files");
this.chunksCollection = database.getCollection(bucketName + ".chunks");
// ensure standard indexes as long as collections are small
try {
if (filesCollection.count() < 1000) {
filesCollection.createIndex(new BasicDBObject("filename", 1).append("uploadDate", 1));
}
if (chunksCollection.count() < 1000) {
chunksCollection.createIndex(new BasicDBObject("files_id", 1).append("n", 1), new BasicDBObject("unique", true));
}
} catch (MongoException e) {
// TODO: Logging
}
filesCollection.setObjectClass(GridFSDBFile.class);
}
/**
* Gets the list of files stored in this gridfs, sorted by filename.
*
* @return cursor of file objects
*/
public DBCursor getFileList() {
return filesCollection.find().sort(new BasicDBObject("filename", 1));
}
/**
* Gets a filtered list of files stored in this gridfs, sorted by filename.
*
* @param query
* filter to apply
* @return cursor of file objects
*/
public DBCursor getFileList(final DBObject query) {
return filesCollection.find(query).sort(new BasicDBObject("filename", 1));
}
/**
* Gets a sorted, filtered list of files stored in this gridfs.
*
* @param query
* filter to apply
* @param sort
* sorting to apply
* @return cursor of file objects
*/
public DBCursor getFileList(final DBObject query, final DBObject sort) {
return filesCollection.find(query).sort(sort);
}
/**
* Finds one file matching the given objectId. Equivalent to findOne(objectId).
*
* @param objectId
* the objectId of the file stored on a server
* @return a gridfs file
* @throws com.mongodb.MongoException
*/
public GridFSDBFile find(final ObjectId objectId) {
return findOne(objectId);
}
/**
* Finds one file matching the given objectId.
*
* @param objectId
* the objectId of the file stored on a server
* @return a gridfs file
* @throws com.mongodb.MongoException
*/
public GridFSDBFile findOne(final ObjectId objectId) {
return findOne(new BasicDBObject("objectId", objectId));
}
/**
* Finds one file matching the given filename.
*
* @param filename
* the name of the file stored on a server
* @return the gridfs db file
* @throws com.mongodb.MongoException
*/
public GridFSDBFile findOne(final String filename) {
return findOne(new BasicDBObject("filename", filename));
}
/**
* Finds one file matching the given query.
*
* @param query
* filter to apply
* @return a gridfs file
* @throws com.mongodb.MongoException
*/
public GridFSDBFile findOne(final DBObject query) {
return injectGridFSInstance(filesCollection.findOne(query));
}
/**
* Finds a list of files matching the given filename.
*
* @param filename
* the filename to look for
* @return list of gridfs files
* @throws com.mongodb.MongoException
*/
public List find(final String filename) {
return find(new BasicDBObject("filename", filename));
}
/**
* Finds a list of files matching the given filename.
*
* @param filename
* the filename to look for
* @param sort
* the fields to sort with
* @return list of gridfs files
* @throws com.mongodb.MongoException
*/
public List find(final String filename, final DBObject sort) {
return find(new BasicDBObject("filename", filename), sort);
}
/**
* Finds a list of files matching the given query.
*
* @param query
* the filter to apply
* @return list of gridfs files
* @throws com.mongodb.MongoException
*/
public List find(final DBObject query) {
return find(query, null);
}
/**
* Finds a list of files matching the given query.
*
* @param query
* the filter to apply
* @param sort
* the fields to sort with
* @return list of gridfs files
* @throws com.mongodb.MongoException
*/
public List find(final DBObject query, final DBObject sort) {
List files = new ArrayList();
DBCursor cursor = filesCollection.find(query);
if (sort != null) {
cursor.sort(sort);
}
try {
while (cursor.hasNext()) {
files.add(injectGridFSInstance(cursor.next()));
}
} finally {
cursor.close();
}
return Collections.unmodifiableList(files);
}
private GridFSDBFile injectGridFSInstance(final Object o) {
if (o == null) {
return null;
}
if (!(o instanceof GridFSDBFile)) {
throw new IllegalArgumentException("somehow didn't get a GridFSDBFile");
}
GridFSDBFile f = (GridFSDBFile) o;
f.fs = this;
return f;
}
/**
* Removes the file matching the given id.
*
* @param id
* the id of the file to be removed
* @throws com.mongodb.MongoException
*/
public void remove(final ObjectId id) {
if (id == null) {
throw new IllegalArgumentException("file id can not be null");
}
filesCollection.remove(new BasicDBObject("_id", id));
chunksCollection.remove(new BasicDBObject("files_id", id));
}
/**
* Removes all files matching the given filename.
*
* @param filename
* the name of the file to be removed
* @throws com.mongodb.MongoException
*/
public void remove(final String filename) {
if (filename == null) {
throw new IllegalArgumentException("filename can not be null");
}
remove(new BasicDBObject("filename", filename));
}
/**
* Removes all files matching the given query.
*
* @param query
* filter to apply
* @throws com.mongodb.MongoException
*/
public void remove(final DBObject query) {
if (query == null) {
throw new IllegalArgumentException("query can not be null");
}
for (final GridFSDBFile f : find(query)) {
f.remove();
}
}
/**
* Creates a file entry. After calling this method, you have to call save to persist the file object.
*
* @param data
* the file's data
* @return a gridfs input file
*/
public GridFSInputFile createFile(final byte[] data) {
return createFile(new ByteArrayInputStream(data), true);
}
/**
* Creates a file entry. After calling this method, you have to call save to persist the file object.
*
* @param f
* the file object
* @return a gridfs input file
* @throws IOException
*/
public InputFile createFile(final File f) throws IOException {
FileInputStream in = new FileInputStream(f);
try {
return createFile(in, f.getName(), true);
} finally {
if (in != null) {
in.close();
}
}
}
/**
* Creates a file entry. After calling this method, you have to call save to persist the file object.
*
* @param in
* an inputstream containing the file's data
* @return a gridfs input file
*/
public InputFile createFile(final InputStream in) {
return createFile(in, null);
}
/**
* Creates a file entry. After calling this method, you have to call save to persist the file object.
*
* @param in
* an inputstream containing the file's data
* @param closeStreamOnPersist
* indicate the passed in input stream should be closed once the data chunk persisted
* @return a gridfs input file
*/
public GridFSInputFile createFile(final InputStream in, final boolean closeStreamOnPersist) {
return createFile(in, null, closeStreamOnPersist);
}
/**
* Creates a file entry. After calling this method, you have to call save to persist the file object.
*
* @param in
* an inputstream containing the file's data
* @param filename
* the file name as stored in the db
* @return a gridfs input file
*/
public InputFile createFile(final InputStream in, final String filename) {
return new GridFSInputFile(this, in, filename);
}
/**
* Creates a file entry. After calling this method, you have to call save to persist the file object.
*
* @param in
* an inputstream containing the file's data
* @param filename
* the file name as stored in the db
* @param closeStreamOnPersist
* indicate the passed in input stream should be closed once the data chunk persisted
* @return a gridfs input file
*/
public GridFSInputFile createFile(final InputStream in, final String filename, final boolean closeStreamOnPersist) {
return new GridFSInputFile(this, in, filename, closeStreamOnPersist);
}
/**
* Creates a file entry.
*
* @param filename
* the file name as stored in the db
* @return a gridfs input file
* @see GridFS#createFile()
*/
public GridFSInputFile createFile(final String filename) {
return new GridFSInputFile(this, filename);
}
/**
* This method creates an empty {@link GridFSInputFile} instance. On this instance an {@link java.io.OutputStream} can be obtained using
* the {@link GridFSInputFile#getOutputStream()} method. You can still call {@link GridFSInputFile#setContentType(String)} and
* {@link GridFSInputFile#setFilename(String)}. The file will be completely written and closed after calling the
* {@link java.io.OutputStream#close()} method on the output stream.
*
* @return GridFS file handle instance.
*/
public GridFSInputFile createFile() {
return new GridFSInputFile(this);
}
/**
* Gets the bucket name used in the collection's namespace. Default value is 'fs'.
*
* @return the name of the file bucket
*/
public String getBucketName() {
return bucketName;
}
/**
* Gets the database used.
*
* @return the database
*/
public DB getDB() {
return database;
}
/**
* Gets the {@link DBCollection} in which the file's metadata is stored.
*
* @return the collection
*/
/* package */DBCollection getFilesCollection() {
return filesCollection;
}
/**
* Gets the {@link DBCollection} in which the binary chunks are stored.
*
* @return the collection
*/
/* package */DBCollection getChunksCollection() {
return chunksCollection;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy