Uploaded image for project: 'Node.js Driver'
  1. Node.js Driver
  2. NODE-4775

Docs: Slicing when piping to readStream

    • Type: Icon: Task Task
    • Resolution: Fixed
    • Priority: Icon: Unknown Unknown
    • 4.12.0
    • Affects Version/s: 4.11.0
    • Component/s: GridFS
    • 2
    • 5
    • Not Needed
    • Not Needed

      We've developed a simple file server using Express which streams files to a user:

       

      app.get("/files/:id", async function (req, res) {
      
          let id = req.params.id;
      
          if(id) {
      
              //Allow file extensions for better iOS support
      
              id = id.split(".");
              id = new ObjectId(id[0]);
      
              let readStream = null;
              let timeoutTimer = setTimeout(() => {
                  if(readStream) {
                      readStream.destroy();
                      console.log(`Forced closing stream: ${id}`);
                  }
              },120000);
      
              const docs = await gfs.find({_id: id}).toArray();
      
              if (docs.length) {
      
                  const file = docs[0];
      
      
                  res.setHeader("Content-Type", file.contentType);
                  res.setHeader("Accept-Ranges", "bytes");
      
      
                  let range = req.headers.range;
      
                  if (range) {
                      let parts = range.replace(/bytes=/, "").split("-");
                      let partialstart = parts[0];
                      let partialend = parts[1];
      
                      let total = file.length;
                      let start = parseInt(partialstart, 10);
                      let end = partialend ? parseInt(partialend, 10) : total - 1;
                      let chunksize = (end - start) + 1;
      
      
                      res.status(206);
                      res.setHeader("Content-Range", "bytes " + start + "-" + end + "/" + total);
                      res.setHeader("Content-Length", chunksize);
      
                      readStream = gfs.openDownloadStream(id, {start, end: total});
      
      
                  } else {
                      res.setHeader("Content-Length", file.length);
      
                      readStream = gfs.openDownloadStream(id);
                  }
      
                  readStream.on("close",() => {
                      clearTimeout(timeoutTimer);
                  });
      
                  readStream.on("error",(e) => {
                      console.error(e);
                  });
      
                  // Sending file
                  return readStream.pipe(res);
      
      
              }
      
          }
      
          return res.redirect("https://www.skibbel.com/");
      
      });

      After a few hours, our memory is full of JSArrayBufferData objects containing buffer data and references to FindCursor. The objects don't get removed by the garbage collector. We also get several timeout messages (like mentioned in the code above) which show, that the readStream was never closed, causing a memory leak.

            Assignee:
            neal.beeken@mongodb.com Neal Beeken
            Reporter:
            developer@nextoo.de Mike K
            Daria Pardue
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: