1

I am working on a React application with a node and mongo backend. The mongo backend is going to be storing images using Gridfs-stream. I have implemented the saving of images successfully, but now am having trouble pulling specific images from the database.

The function for gfs.files.findOne was working correctly until I moved it to a separate file and added it to the module exports. I can't figure out what could be causing this to fail executing.

Getting image in database.js:

exports.getFile = (filename) => {
  console.log('loading file: ' + filename);
  gfs.files.findOne({ filename : filename }, (err, file) => {
    console.log('finding file');
    if (file) {
      // checking specifically for image here
      if (file.contentType == 'image/png' || file.contentType == 'image/jpeg') {
        res.set('Content-Type', file.mimetype);
        const readstream = gfs.createReadStream(file.filename);
        console.log('returning readstream');
        return readstream; 
      }
      else {
        console.log('error loading');
        const err = { "status": "error", "details": "File is not an image" };
        return err;
      }
    }
    else {
      console.log('error loading');
      const err = { "status": "error", "details": "Failed to find specified file" };
      return err;
    }
  });
  console.log('function ending');
}

Calling the function in the api route users.js:

let rs = database.getFile(pic.profilePicture);
if (rs.status && rs.status === "error") {
    res.json(rs);
}
else {
    // we have a readstream
    rs.pipe(res);
}

Console output in terminal:

[0] testing retrieving profile picture
[0] loading file: 7be7c6a99a96023763b753febd85a92e.png
[0] function ending
[0] events.js:173
[0]       throw er; // Unhandled 'error' event
[0]       ^
[0] 
[0] TypeError: Cannot read property 'status' of undefined
[0]     at User.getProfilePicture (/Users/zachdobbs/Documents/Projects/Better/routes/api/users.js:44:20)
[0]     at /Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/model.js:4698:16
[0]     at /Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/query.js:4099:12
[0]     at process.nextTick (/Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/query.js:2681:28)
[0]     at processTicksAndRejections (internal/process/next_tick.js:74:9)
[0] Emitted 'error' event at:
[0]     at /Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/model.js:4700:13
[0]     at /Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/query.js:4099:12
[0]     at process.nextTick (/Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/query.js:2681:28)
[0]     at processTicksAndRejections (internal/process/next_tick.js:74:9)
[0] [nodemon] app crashed - waiting for file changes before starting...

As far as I can see the gfs.files.findOne function is skipping over the entire block and going straight to the end of the function. The only logs being shown are the loading file: ...png and function ending outputs. These logs are found at the beginning and end of the function, but none of the other logs within the function are being executed. I can not figure out why this may be the case. If anyone could help me solve this it would be greatly appreciated.

Zach Dobbs
  • 63
  • 1
  • 7
  • shouldn't you return it as an object? { status: "error", details: "Failed to find specified file" }; you are returning Json later you can do JSON.stringify to send it to client or whatever. – jcuypers Apr 04 '19 at 21:42
  • @jcuypers I suppose so, but making this change does not change any output. The if..else blocks of the code in database.js don't even appear to be getting hit according to the log outputs – Zach Dobbs Apr 04 '19 at 21:49
  • Please print out `err` just after the gfs line: `gfs.files.findOne({ filename : filename }, (err, file) => {` – jcuypers Apr 04 '19 at 21:52
  • @jcuypers adding console.log(err) immediately after that line doesn't change anything. The logs still only output ```loading file: ...``` and ```function ending```. I can't get any logs to print from within the actual ```gfs.files.findOne()``` block – Zach Dobbs Apr 04 '19 at 21:58
  • ok weird. sorry I use mongoose-gridfs. just checking the manual for gridfs-stream. All the examples are of the form `var gfs = Grid(conn.db); gfs.files.find({ filename: 'myImage.png' }).toArray(function (err, files) { if (err) ... console.log(files); })` Alternatively you can use the gfs.findOne-shorthand to find a single file `gfs.findOne({ _id: '54da7b013706c1e7ab25f9fa'}, function (err, file) { console.log(file); });` findOne doesn't seem to have .files. in the name. are you sure of the command – jcuypers Apr 04 '19 at 22:03

1 Answers1

0

Like this:

exports.getFile = (filename) => {
  console.log('loading file: ' + filename);
  gfs.findOne({ filename : filename }, (err, file) => {
    console.log('finding file');
    if (file) {
      // checking specifically for image here
      if (file.contentType == 'image/png' || file.contentType == 'image/jpeg') {
        res.set('Content-Type', file.mimetype);
        const readstream = gfs.createReadStream(file.filename);
        console.log('returning readstream');
        return readstream; 
      }
      else {
        console.log('error loading');
        const error = { status: "error", details: "File is not an image" };
        return error;
      }
    }
    else {
      console.log('error loading');
      const error = { status: "error", details: "Failed to find specified file" + err };
      return error;
    }
  });
  console.log('function ending');
}

and then:

let rs = database.getFile(pic.profilePicture);
if (rs.status && rs.status === "error") {
    res.json(JSON.stringify(rs));
}
else {
    // we have a readstream
    rs.pipe(res);
}
jcuypers
  • 1,774
  • 2
  • 14
  • 23