Can someone provide guidance on how to utilize the GridFSBucket
stream within the streamFile
function?
Below is a functional example where a file on the disc is read and returned as a stream:
import { NextRequest, NextResponse } from "next/server";
import { ReadableOptions } from "stream";
function streamFile(path: string, options?: ReadableOptions): ReadableStream<Uint8Array> {
const downloadStream = fs.createReadStream(path, options); // Replace this
return new ReadableStream({
start(controller) {
downloadStream.on("data", (chunk: Buffer) => controller.enqueue(new Uint8Array(chunk)));
downloadStream.on("end", () => controller.close());
downloadStream.on("error", (error: NodeJS.ErrnoException) => controller.error(error));
},
cancel() {
downloadStream.destroy();
},
});
}
export async function GET(req: NextRequest): Promise<NextResponse> {
const file = req.nextUrl.searchParams.get("file");
const stats: Stats = await fs.promises.stat(file);
const data: ReadableStream<Uint8Array> = streamFile(file);
const res = new NextResponse(data, {
status: 200,
headers: new Headers({
"content-type": "video/mp4",
"content-length": stats.size + "",
}),
});
return res;
}
However, in my case, the data is stored in a mongoDB GridFSBucket. This is how I stream a video file directly from the GridFSBucket:
export const getServerSideProps: GetServerSideProps = async ({
res,
query: { hash }
}) => {
const database = await mongodb()
const Videos = database.collection('videos')
const { fileId } = await Videos.findOne({ uid: hash })
const Files = new GridFSBucket(database)
const id = new ObjectId(fileId)
const file: GridFSFile = await new Promise((resolve, reject) => {
Files.find({
_id: id
}).toArray((err, files) => {
if (err) reject(err)
resolve(files[0])
})
})
const { contentType } = file || {}
res.writeHead('Content-Type', contentType) // contentType is "video/mp4"
Files.openDownloadStream(id)
.on('data', (chunk) => {
res.write(chunk)
})
.on('end', () => {
res.end()
})
.on('error', (err) => {
throw err
})
return {
props: {}
}
}
I am considering using the GridFSBucket
instead of createReadStream
for my task.
However, the use of res.writeHead
and openDownloadStream
poses some challenges. How can I obtain a ReadableStream
? Or is it necessary at all?
I aim to make this conversion because the getServerSideProps
is being employed in an older nextJS application with pages router, and I need to transition to the new app router, hence the requirement for a server route component.