Search code examples
springmongodbmongodb-java

Save an object with image ( save both object data and image too) inside mongoDB using Java


I want to know specifically about saving an object with an image inside it. What I want to do is saving an entire object with image inside it, Image must be saved. I tried this but it saves only File instance with file path. Its not saving the image. Any help would be appreciated. Thank you. Here is my code for saving an object but its saving a file instance instead of an image.

import java.io.File;    
import org.springframework.data.mongodb.core.mapping.Document;
import com.discusit.model.Artwork;

@Document(collection="Artwork")
public class ArtworkImpl implements Artwork {

    private String artworkName;
    private String artworkVersion;
    private String fileName;
    private File file;

    public ArtworkImpl() {

    }

    public ArtworkImpl(String name, String version, String fileName, File file) {
        this.artworkName = name;
        this.artworkVersion = version;
        this.fileName = fileName;
        this.file = file;
    }

    public String getArtworkName() {
        return artworkName;
    }

    public void setArtworkName(String artworkName) {
        this.artworkName = artworkName;
    }

    public String getArtworkVersion() {
        return artworkVersion;
    }

    public void setArtworkVersion(String artworkVersion) {
        this.artworkVersion = artworkVersion;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }   
}

Here is my main method :- NOTE : Main method works fine, but not saving image, instead saving file instance.

public class MainApplication {

    public static void main(String[] args) {

    ApplicationContext ctx = 
                     new AnnotationConfigApplicationContext(SpringMongoConfig.class);
    GridFsOperations gridOperations = 
                      (GridFsOperations) ctx.getBean("gridFsTemplate");

    DBObject metaData = new BasicDBObject();
    metaData.put("extra1", "anything 1");
    metaData.put("extra2", "anything 2");

    InputStream inputStream = null;
    try {
        inputStream = new FileInputStream("/home/discusit/Downloads/birds.jpg");
        gridOperations.store(inputStream, "birds.jpg", "image/jpg", metaData);

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

        System.out.println("Done");
    }

}

I want to save object with image.

UPDATE : I did this but by converting an image to byte array and fetching byte array and converting back to Image, just want to know is there any other way by which I can save an image directly in mongoDB but without converting it to byte array ????


Solution

  • You need to clarify the following about mongoDB:

    1. MongoDB is a document oriented database, in which the documents are stored in a format called BSON and limited to a maximun of 16MB. "Think of BSON as a binary representation of JSON (JavaScript Object Notation) documents"[1].

    The BSON format support a BinData type, in which you can store the binary representation of a file as long as the 16MB limit will not be exceded.

    2. MongoDB provides a way to store files GridFS "GridFS is a specification for storing and retrieving files that exceed the BSON-document size limit of 16MB"[2].

    GridFS divide the files in chunks of 256K and use two collections to store the files, one for metadata and one for the file chunks, this collections are called fs.files and fs.chunks respectively.

    A file stored within these collections, looks like this:

    >db.fs.files.find()
    {
      "_id": ObjectId("51a0541d03643c8cf4122760"),
      "chunkSize": NumberLong("262144"),
      "length": NumberLong("3145782"),
      "md5": "c5dda7f15156783c53ffa42b422235b2",
      "filename": "test.png",
      "contentType": "image/bmp",
      "uploadDate": ISODate("2013-05-25T06:03:09.611Z"),
      "aliases": null,
      "metadata": {
        "extra1": "anything 1",
        "extra2": "anything 2"
      }
    }
    
    
    >db.fs.chunks.find()
    {
    "_id": ObjectId("51a0541e03643c8cf412276c"),
      "files_id": ObjectId("51a0541d03643c8cf4122760"),
      "n": 11,
      "data": BinData(0, "BINARY_DATA_WILL_BE_STORED_HERE")
    }
    .
    .
    

    Note how the ObjectId in the files collections match the files_id in the chunks collections.

    After this clarification the short answer to your question is:

    Yes, you can store the files directly in mongoDB using GridFS.

    In the following link you can find a GridFS working example using Spring Data:

    http://www.mkyong.com/mongodb/spring-data-mongodb-save-binary-file-gridfs-example/

    [1] http://docs.mongodb.org/manual/reference/glossary/#term-bson

    [2] http://docs.mongodb.org/manual/core/gridfs/