جاوااسکریپت - فشرده کردن جریان تصویر با استفاده از archiver و ارسال آن به عنوان پاسخ express


این بر روی Node/Express/Typescript است. من تلاش میکنم یک تصویر در سیستم فایل خود بگیرم، آن را به یک فایل زیپ استریم کنم و سپس این فایل زیپ را به کلاینت استریم کنم. من باید اطمینان حاصل کنم که هر مرحله استریم میشود چون این به گسترش به زیپ کردن چندین فایل منجر خواهد شد، که باید به صورت استریم به کلاینت تحویل داده شوند.

من کد زیر را دارم:

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();

});

با این حال، وقتی به مسیر /images خود دسترسی پیدا میکنم، یک فایل output.zip دریافت میکنم که خالی است.

احساس میکنم که somehow ترتیب لولههایم را به هم زدهام.

من چه چیزی را از دست دادهام؟

پاسخ شماره ۱

مشکل را پیدا کردم. این هم کدی است که کار میکند:

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();

});

من مجبور شدم از archive.append(ps, {name: "image.png"}); استفاده کنم تا جریان تصویر خود را به آرشیو زیپ اضافه کنم.