-
Type: Task
-
Resolution: Fixed
-
Priority: Unknown
-
Affects Version/s: 4.11.0
-
Component/s: GridFS
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.