-1

NOTE: this is NOT a production application. It is a small app that I am making to explore the capabilities of selecting, opening, saving and reading an image from a DB.

I do not know what method I should call to get the correct Buffer data to store image in mongodb. ( I am aware that mongoDB has a 16mb limit on documents )

In my app, I want the user to be able to select an image from a file on their pc, give the user a preview of the image, then when the user hits submit (not shown here) save the image into mongodb

I know when the user clicks the "choose file" button I can get the file like this:

    const file = event.target.files[0]

    if (!file) {
        // user has hit the cancel button
        return;
      }        

    //console.log(file);

I can get information about the file:

    console.log(file.type);
    console.log(file.size);

and here is how the image is read:

    let fr = new FileReader();
    fr.readAsDataURL(file);
    fr.onload = (e) =>{
        this.productImageAdd(e.target.result);
    }

This is how the image is stored in the (react) component state

productImageAdd = (file) => {

    let temp = this.state["filesArray"] || [];
    temp.push(file);
    this.setState({"filesArray": temp});
}

Here is the state of my component

this.state = {
  filesArray: [],
};

In another component, I get a listing of all the images and then map them to an item for display:

return filesArray.map((file, index) => (
  <FileDropZoneItem key={index} id={index} file={file} />
));

In FileDropZoneItem, this is how images are "previewed":

    return (
        <li className="flex-item ">
          <img src={file} width="200" height="200"/>
        </li>
    );

I saw this stackoverflow question and I am moving towards that to store the image in MongoDB:

Store an image in MongoDB using Node.js/Express and Mongoose

In that post, their schema is like this:

var schema = new Schema({
    img: { data: Buffer, contentType: String }
});

And they store the image like this:

var A = mongoose.model('A', schema);
var a = new A;
a.img.data = fs.readFileSync(imgPath);
a.img.contentType = 'image/png';

but I don't really know the difference between fs.readFileSync and fr.readAsDataURL.

Will storing to mongodb work using fr.readAsDataURL or do I need fs.readFileSync ?

I also saw: Difference between readAsBinaryString() and readAsDataURL() in HTML5 FileReader API

MLissCetrus
  • 423
  • 3
  • 21
  • `but I don't really know the difference between fs.readFileSync and fr.readAsDataURL.` one is nodejs code the other is browser code. – tkausl Jan 21 '19 at 21:00
  • @tkausl Do they return the same thing? – MLissCetrus Jan 21 '19 at 21:03
  • @MLissCetrus No. [`fr.readAsDataURL`](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL) doesn't return anything, while [`fs.readFileSync`](https://nodejs.org/api/fs.html#fs_fs_readfilesync_path_options) returns the contents of the file at the given path. – Itai Steinherz Jan 21 '19 at 21:27
  • @Itai Steinherz ... literally, I agree with you, however, in the code that I have provided, it eventually returns a value in "e.target.result" - which is the subject of this post and what I am interested in learning about – MLissCetrus Jan 21 '19 at 21:36
  • @MLissCetrus See [the File API docs](https://w3c.github.io/FileAPI/#filedata-attr). – Itai Steinherz Jan 21 '19 at 21:39

1 Answers1

1

From the MongoDB manual GridFS GridFS uses two collections to store files. One collection stores the file chunks, and the other stores file metadata. The section GridFS Collections describes each collection in detail.

For reference you can read Storing images in MongoDB

readAsDataURL permits to store the images inside the JSON document encoded as base64 characters. Given the size of the Products pictures 200px x 200px seems the best option for your hello world app.

readFileSync can have blocking issues in the server like Nodejs for image handling behavior and reads the binary file to store it as Binary Data.

IMO the best solution is to not overload mongoDB and Nodejs with the image handling and store only an URL to the image in the mongoDB document leaving the image serving process to a proxy like nginx.

The Gridfs option depends on the driver used. Following is Gridfs use in Nodejs that uses its own reader:

fs.createReadStream('./meistersinger.mp3').
pipe(bucket.openUploadStream('meistersinger.mp3')).
Yones
  • 95
  • 7
  • storing the URL and retrieving the image sounds like a super suggestion... for a production environment or a "big" app in the real world... I have updated my question to indicate this is a "hello world" type application. – MLissCetrus Jan 21 '19 at 22:27
  • storing the images like binary data in db as BinData and under Gridfs you loose some control over the media but it is worth noting to test it. The other two options dataAsURL base64 encoded for thumbnails and DBref to file on disk are most reliable. Good test. – Yones Jan 23 '19 at 17:06
  • https://stackoverflow.com/users/10899806/yones - Was this a good question? did it outline all of the necessary information required for you to come up with an answer? If so, can you please up vote it? thanks – MLissCetrus Apr 13 '20 at 21:03