typescriptnext.jsnode-archiver

How to download zip archive using Archiver and Next.js?


I'm using Next.js and want to create a route to download a zip archive created with Archiver.

The problem is: how to pass Archiver to NextResponse?

Here is my code:

const filesPath = "./data/files/";
const archive = Archiver('zip', { zlib: { level: 9 } });
GetFilesFromKey(token).forEach((filename) => {
    archive.file(filesPath + token + "/" + filename.filename, { name: filename.filename });
});
archive.finalize();

// Here needs to be the code that converts "archive" to "BodyInit"

return new NextResponse(SOME BODY INIT, {
    headers: {
        'Content-Disposition': `attachment; filename="files.zip"`,
        'Content-Type': 'application/octet-stream',
    },
});

Solution

  • I fixed it:

    const filesPath = "./data/files/";
    const archive = Archiver('zip', { zlib: { level: 9 } });
    const readableStream = new ReadableStream({
        start(controller) {
            // Pipe data from the archive to the stream
            archive.on('data', (chunk) => {
                controller.enqueue(chunk);
            });
    
            // Handle errors
            archive.on('error', (err) => {
                console.error('Archiver error:', err);
                controller.error(err);
            });
    
            // Close the stream when the archive finishes
            archive.on('end', () => {
                controller.close();
            });
    
            // Add files to the archive
            GetFilesFromKey(token).forEach((filename) => {
                archive.file(filesPath + token + "/" + filename.filename, { name: filename.filename });
            });
    
            // Finalize the archive
            archive.finalize();
        },
    });
    
    return new NextResponse(readableStream, {
        headers: {
            'Content-Disposition': `attachment; filename="files.zip"`,
            'Content-Type': 'application/octet-stream',
        },
    });