In the previous recipe, we saw how to store data to GridFS using the command-line utility called mongofiles
, which comes with MongoDB to manage large data files. To get an idea of what GridFS is and what collections are used behind the scenes to store the data, refer to the previous recipe. In this recipe, we will look at storing data to GridFS using a Java client. The program will be a highly scaled down version of the mongofiles
utility and focuses only on how to store, retrieve, and delete data rather than trying to provide a lot of options such as mongofiles
do.
Refer to the Connecting to a single node from a Java client recipe from Chapter 1, Installing and Starting the MongoDB Server, for all the necessary setup for this recipe. If you are interested in more details on Java drivers, refer to the following recipes in Chapter 3, Programming Language Drivers:
Open a Mongo shell and connect to the local mongod
instance listening to port 27017
. For this recipe, we will be using the project mongo-cookbook-gridfs
. This project is available in the source code bundle downloadable from the book's website. The folder needs to be extracted on the local filesystem. Open a terminal on your operating system and go to the root of the project extracted. It should be the directory where the pom.xml
file is found. Also, save the glimpse_of_universe-wide.jpg
file on the local filesystem, just as in the previous recipe. This file can be found in the downloadable code bundle from the book's website.
> use test > db.fs.chunks.drop() > db.fs.files.drop()
$ mvn clean compile exec:java -Dexec.mainClass=com.packtpub.mongo.cookbook.GridFSTests -Dexec.args="put ~/glimpse_of_universe-wide.jpg universe.jpg"
Successfully written to universe.jpg, details are: Upload Identifier: 5314c05e1c52e2f520201698 Length: 2711259 MD5 hash: d894ec31b8c5addd0c02060971ea05ca Chunk Side in bytes: 262144 Total Number Of Chunks: 11
> db.fs.files.findOne({filename:'universe.jpg'}) > db.fs.chunks.find({}, {data:0})
get
operation, is writable to the user.$ mvn clean compile exec:java -Dexec.mainClass=com.packtpub.mongo.cookbook.GridFSTests -Dexec.args="get '~/universe.jpg' universe.jpg"
Connected successfully.. Successfully written 2711259 bytes to ~/universe.jpg
$ mvn clean compile exec:java -Dexec.mainClass=com.packtpub.mongo.cookbook.GridFSTests -Dexec.args="delete universe.jpg"
Connected successfully.. Removed file with name 'universe.jpg' from GridFS
The com.packtpub.mongo.cookbook.GridFSTests
class accepts three types of operations, put
, get
, and delete
, to upload a file to GridFS, get contents from GridFS to a local filesystem, and delete files from GridFS respectively.
The class accepts up to three parameters. The first one is the operation with valid values as get
, put
, and delete
. The second parameter is relevant for the get
and put
operations and is the name of the file on the local filesystem to write the downloaded content to, or from which the content is sourced for upload. The third parameter is the name of the file in GridFS, which is not necessarily the same as the name on the local filesystem. However, for delete
, only the filename on GridFS is needed for deletion purposes.
Let us see some important snippets of code from the class that is specific to GridFS.
Open the com.packtpub.mongo.cookbook.GridFSTests
class in your favorite IDE and look for the handlePut
, handleGet
, and handleDelete
methods. These are the methods where all the logic is. First, we will start with the handlePut
method, which is meant to upload the contents of the file from the local filesystem to GridFS.
Irrespective of which operation we do, we will create an instance of the com.mongodb.gridfs.GridFS
class. In our case, we instantiated it as follows:
GridFS gfs = new GridFS(client.getDB("test"));
The constructor of this class takes the database instance of the com.mongodb.DB
class in which we wish to create the GridFS tables fs.chunks
and fs.files
, which will store the uploaded content. Once the instance of GridFS is created, we will invoke the createFile
method on it. This method accepts two parameters; the first one is InputStream
, which sources the bytes of the content to be uploaded, and the second parameter is the name of the file that will be saved on GridFS. However, this method doesn't create the file on GridFS but returns an instance of com.mongodb.gridfs.GridFSInputFile
. The upload will happen only when we call the save
method in this returned object. There are a few overloaded variants of this createFile
method. For more details, refer to the Javadoc of the com.mongodb.gridfs.GridFS
class.
Our next method is handleGet
, which
gets the contents of the file saved on GridFS to a local filesystem. Similar to the com.mongodb.DBCollection
class, the class com.mongodb.gridfs.GridFS
has the find
and findOne
methods to search. However, instead of accepting any DBObject
query, find
and findOne
in GridFS accept the filename or the ObjectId
value of the document to search in the fs.files
collection. Similarly, the return value is not a DBCursor
but an instance of com.mongodb.gridfs.GridFSDBFile
. This class has various methods that let us get the InputStream
of the bytes of the file present on GridFS. Other methods are writeTo
, which writes to the given file or OutputStream
and a getLength
method that give the number of bytes in the file. For details, refer to the Javadoc of the com.mongodb.gridfs.GridFSDBFile
class.
Finally, we look at the handleDelete
method that is used to delete the files on GridFS and is the simplest of the lot. The method on the object of GridFS is remove
, which accepts a string argument that is the name of the file to delete on the server. The return type of this method is void. So, irrespective of whether the content is present on GridFS or not, the method will not return a value nor throw an exception if a name is provided to this method for a file that doesn't exist.