如何在AWS Lambda中用Node.js向现有Zip文件夹添加JSON文件?
Great question! Unfortunately, easy-zip is a bit outdated and doesn’t support modifying existing zip files reliably. But there are two solid Node.js modules you can use instead: adm-zip (simple, good for most cases) and yauzl + yazl (low-level, ideal for large zips that can’t fit in memory). Let’s break down how to use both, including how to implement this in AWS Lambda.
Using adm-zip (Simplest Approach)
Adm-zip is a popular, easy-to-use module that supports reading existing zips and adding new files directly to them.
Step 1: Install the module
npm install adm-zip
Step 2: Basic Local Usage Code
This example loads your existing zip, adds a JSON file, and saves the modified zip back to disk:
const AdmZip = require('adm-zip'); const fs = require('fs'); // Configure paths and filenames const existingZipPath = './downloaded-from-s3.zip'; const jsonFilePath = './your-data.json'; const internalZipFileName = 'metadata.json'; // Name the file will have inside the zip // Load the existing zip const zip = new AdmZip(existingZipPath); // Read the JSON file content const jsonContent = fs.readFileSync(jsonFilePath, 'utf8'); // Add the JSON content to the zip zip.addFile(internalZipFileName, Buffer.from(jsonContent, 'utf8')); // Save the modified zip zip.writeZip('./updated-zip.zip'); console.log('JSON file added to zip successfully!');
For AWS Lambda Environment
Lambda restricts writing to the /tmp directory only (which offers up to 10GB of space in newer runtimes). You’ll need to download the zip from S3 to /tmp, modify it, then upload the updated zip back to S3.
Step 1: Dependencies
adm-zip needs to be included in your deployment package, while aws-sdk is pre-installed in Lambda environments.
Step 2: Lambda Function Code
const AdmZip = require('adm-zip'); const AWS = require('aws-sdk'); const s3 = new AWS.S3(); const fs = require('fs'); const path = require('path'); exports.handler = async (event) => { // Configuration - adjust these values to match your setup const s3Bucket = 'your-s3-bucket-name'; const originalZipKey = 'path/to/existing-zip.zip'; const modifiedZipKey = 'path/to/updated-zip.zip'; const jsonContent = JSON.stringify({ user: 'Vishnu', timestamp: new Date().toISOString() }); // Your JSON data const internalZipFileName = 'added-data.json'; try { // 1. Download the original zip from S3 to /tmp const zipResponse = await s3.getObject({ Bucket: s3Bucket, Key: originalZipKey }).promise(); const tempZipPath = path.join('/tmp', 'existing.zip'); fs.writeFileSync(tempZipPath, zipResponse.Body); // 2. Load the zip and add the JSON file const zip = new AdmZip(tempZipPath); zip.addFile(internalZipFileName, Buffer.from(jsonContent, 'utf8')); // 3. Save the modified zip to /tmp const modifiedTempPath = path.join('/tmp', 'updated.zip'); zip.writeZip(modifiedTempPath); // 4. Upload the modified zip back to S3 await s3.putObject({ Bucket: s3Bucket, Key: modifiedZipKey, Body: fs.readFileSync(modifiedTempPath) }).promise(); return { statusCode: 200, body: JSON.stringify('JSON file added to zip successfully!') }; } catch (error) { console.error('Error processing zip:', error); return { statusCode: 500, body: JSON.stringify('Failed to modify zip file') }; } };
Lambda-specific Notes:
- Permissions: Ensure your Lambda execution role has
s3:GetObjectfor the original zip ands3:PutObjectfor the modified zip. - Large Zips: If your zip is multiple gigabytes,
adm-zipmay cause out-of-memory errors since it loads the entire zip into memory. For these cases, use theyauzl + yazlapproach below. - Ephemeral Storage:
/tmpis cleared after Lambda invocations, so don’t rely on it for persistent storage.
Alternative: yauzl + yazl (For Large Zips)
This approach streams zip content instead of loading everything into memory, making it ideal for large files.
Step 1: Install Modules
npm install yauzl yazl
Step 2: Streaming Code (Local Example)
const yauzl = require('yauzl'); const yazl = require('yazl'); const fs = require('fs'); // Open the existing zip for streaming yauzl.open('./existing.zip', { lazyEntries: true }, (err, zipIn) => { if (err) throw err; // Create a new zip file to write to const zipOut = new yazl.ZipFile(); const outputStream = fs.createWriteStream('./modified.zip'); zipOut.outputStream.pipe(outputStream); // Copy all existing entries from the original zip to the new one zipIn.readEntry(); zipIn.on('entry', (entry) => { zipIn.openReadStream(entry, (err, readStream) => { if (err) throw err; zipOut.addReadStream(readStream, entry.fileName); zipIn.readEntry(); }); }); // Add the JSON file once all existing entries are copied zipIn.on('end', () => { zipOut.addBuffer( Buffer.from(JSON.stringify({ data: 'large-zip-compatible' }), 'utf8'), 'new-json-file.json' ); zipOut.end(); }); });
In Lambda, you can adapt this to stream directly to S3 instead of writing to /tmp (using s3.upload with streams) for even better memory efficiency.
内容的提问来源于stack exchange,提问作者Vishnu Ranganathan

