javascript - Komprimera bildström med archiver och skicka som express-svar


Detta är på Node/Express/Typescript. Jag försöker få en bild på mitt filsystem, strömma den till en zip-fil och sedan strömma denna zip-fil till klienten. Jag måste se till att varje steg strömmas eftersom detta kommer att utökas till att zippa flera filer, som måste strömmas till klienten som en zip.

Jag har följande kod:

import express, { Application, Request, Response } from "express";
import fs from "fs";
import stream from "stream";
import archiver from "archiver";

app.get("/images", async (req: Request, res: Response) => {
    const r = fs.createReadStream("appicon.png");
    const ps = new stream.PassThrough();

    // stream the image
    stream.pipeline(
        r,
        ps,
        (err) => {
            if (err) {
                console.log(err);
                return res.sendStatus(400);
            }
        }
    );


    // zip the image and send it
    let archive = archiver("zip");

    archive.on("end", () => {
        console.log(archive.pointer() + " total bytes");
        console.log("archiver finalized");
    })

    archive.on('error', (err) => {
        return res.status(500).send({
            message: err
        });
    })

    res.attachment('output.zip');
    ps.pipe(archive); 
    archive.pipe(res);



    archive.finalize();

});

Men när jag går till min /images-rutt får jag en output.zip-fil som är tom.

Jag känner att jag på något sätt blandar ihop ordningen på mina rör.

Vad missar jag?

Svar #1

Jag lista ut problemet. Här är koden som fungerar:

app.get("/images", async (req: Request, res: Response) => {
    const r = fs.createReadStream("appicon.png");
    const ps = new stream.PassThrough();

    stream.pipeline(
        r,
        ps,
        (err) => {
            if (err) {
                console.log(err);
                return res.sendStatus(400);
            }
        }
    );

    //r.pipe(ps); // alternative way to do it without pipeline


    // zip the image and send it
    let archive = archiver("zip");

    archive.on("end", () => {
        console.log(archive.pointer() + " total bytes");
        console.log("archiver finalized");
    })

    archive.on('error', (err) => {
        return res.status(500).send({
            message: err
        });
    })

    // name the output file
    res.attachment("output.zip");

    // pipe the zip to response
    archive.pipe(res);

    // add the image from stream to archive
    archive.append(ps, {name: "image.png"});

    archive.finalize();

});

Jag var tvungen att använda archive.append(ps, {name: "image.png"}); för att lägga till min bildström i zip-arkivet.

Relaterade artiklar