简体   繁体   中英

How to copy and zip folder from stream rather than disk- Node.js

My code below copies the /template directory into the /theme directory after replacing some variables.

The /theme directory is zipped and returned in an HTTP response.

This works locally, but fails once I push it up to Netlify. It fails because I don't have write privileges from within the function. I believe the solution is to write to a stream instead of to the disk, but I'm unsure of how to do that after reading through some docs.

const copy = require("copy-template-dir");
const path = require("path");
const fs = require("fs");
const JSZip = require("jszip");

const inDir = path.join(__dirname, "template");
const outDir = path.join(__dirname, "theme");

exports.handler = async (event, context) => {
    // Searches /template, replaces the variables, and copies the files to /theme
    function makeCopy() {
        return new Promise(function (resolve, reject) {
            //returning promise
            // Theme Variables to Find and Replace
            const vars = {
                theme_name: "Theme Name",
                theme_slug: "theme-slug",
                author_name: "Author Name",
            };

            // Get vars from query string
            if (event.queryStringParameters) {
                vars.theme_name = event.queryStringParameters.name || vars.theme_name;
                vars.theme_slug = event.queryStringParameters.name || vars.theme_slug;
                vars.author_name = event.queryStringParameters.author || vars.author_name;
            }

            copy(inDir, outDir, vars, (err, createdFiles) => {
                if (err) throw err;
                resolve();
            });
        });
    }

    // Loops contents of the /theme directory and creates a zip file
    const addFilesFromDirectoryToZip = (directoryPath = "", zip) => {
        const directoryContents = fs.readdirSync(directoryPath, {
            withFileTypes: true,
        });

        directoryContents.forEach(({ name }) => {
            const path = `${directoryPath}/${name}`;

            if (fs.statSync(path).isFile()) {
                zip.file(path, fs.readFileSync(path, "utf-8"));
            }

            if (fs.statSync(path).isDirectory()) {
                addFilesFromDirectoryToZip(path, zip);
            }
        });
    };

    // Zip the theme
    async function makeZip() {
        var zip = new JSZip();

        addFilesFromDirectoryToZip("theme", zip);

        const zipAsBase64 = await zip.generateAsync({ type: "base64" });
        return zipAsBase64;
    }
    
    const myCopy = await makeCopy();
    const zip = await makeZip();

    // Return the zip
    return {
        statusCode: 200,
        body: zip,
        headers: {
            "Content-Type": "application/zip",
            "Content-Disposition": "attachment; filename=theme.zip",
        },
    };
};

The answer is not Node streams. Since this is a lambda function, I just needed to make use of the writable /tmp folder.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM