zip file download using node and vue - node.js

I am using nodejs archive for creating my zip file. I need to download this zip file via axios.
this is my node js code.
let zipFile = fs.createWriteStream(zipFilePath);
var archive = ar('zip');
zipFile.on('close', () => {
console.log(archive.pointer() + ' total bytes');
console.log('archiver has been finalized and the output file descriptor has closed.');
});
zipFile.on('end', () => {
console.log('Data has been drained');
});
archive.on('warning', (err) => {
if (err.code === 'ENOENT') {
console.log('worning');
} else {
throw err;
}
});
archive.on('error', (err) => {
throw err;
res.status(500).send({ error: err.message });
});
archive.on('finish', () => {
console.log("zip file generate");
});
archive.pipe(zipFile);
archive.pipe(res);
res.on('close', (err) => {
if (err) {
throw err;
}
console.log('Archive wrote %d bytes', archive.pointer());
})
archive.append(fs.createReadStream(englishFilePath), { name: englishFileName });
archive.append(fs.createReadStream(spanishFilePath), { name: spanishFileName });
archive.finalize();
this is my vuejs code for download the zip file
const url = window.URL.createObjectURL(new Blob([res.body]));
const link = document.createElement("a");
link.setAttribute('href', URL)
link.href = url;
link.setAttribute("download", zipfileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
now I am able to download a zip file, but it was corrupted.

Related

Firebase Function fails with `Couldn't handle response` for Archive

I'm trying to zip a few audio files from a bucket, then download the zip on Firebase functions, everything works well on local emulator, also raised memory to 1Gb and 300 for timeout, but the https function fails with a generic message, "Couldn't handle response".
Here's the code.
const workingDir = join(tmpdir(), 'zip' + +new Date());
await fs.ensureDir(workingDir);
const archive = archiver('zip', { zlib: { level: 9 } });
archive.on('warning', function (err) {
if (err.code === 'ENOENT') {
console.log('Warning', err);
} else {
throw err;
}
});
archive.on('error', function (err) {
console.log('error', err);
throw err;
});
res.attachment(+new Date() + '.zip').type('zip');
archive.pipe(res);
archive.on('end', () => res.end());
archive.directory(workingDir, false);
archive.finalize();

Sending webm blob to nodejs and saving it on the server

I'm having troubles saving an incoming webm blob to the server. I'm using react-video-recorder on NextJS like this:
<VideoRecorder
onRecordingComplete={(videoBlob) => {
// Do something with the video...
fetch("/api/video",
method: "post",
body: videoBlob,
})
.then(function (response) {
console.log("done");
return response;
})
.catch(function (err) {
console.log('error', err);
});
console.log(url);
// output: blob:http://localhost:3000/99a5b711-f3d5-481d-9e04-8981d1be3727
console.log(videoBlob);
// output BlobĀ {size: 307028, type: "video/webm;codecs="vp8,opus""}
}}
/>
On the api side I'm trying to save the file like this. It does save something, but is only the first chunk or buffer. How can I capture and write the file to my server?
export default async (req, res) => {
fs.writeFile('test.webm', req.body, function (err) {
if (err) return console.log(err);
console.log('video saved');
} );
}
I did that task by doing this.
I saved the recordingChunks/Video blob to a state and then sent it to the Nodejs server from Reactjs Frontend
FrontEnd code:-
const blob = new Blob(context.data.recordedChunks, {
type: "video/webm",
});
const fd = new FormData()
fd.append('video', blob)
axios.post(`${process.env.REACT_APP_BASE_URL}/video/blob_video`, fd)
.then((res) => console.log(res.data))
.catch((err) => console.log(err))
Backend code:-
router.post('/blob_video', async (req, res) => {
try {
if (req.files.video !== undefined) {
const video = req.files.video // this is your file do what ever you want with it
const videoname = Date.now() + req.files.video.name + ".webm"
video.mv(`${__dirname}/../your_path/${videoname}`, err => {
if (err) {
console.log(err)
return res.json({ err })
}
})
}
res.json(req.body)
} catch (err) {
res.json({ success: false, err: err, msg: "Server error" })
console.log(err)
}
})
Using express-fileupload to upload a file you can do it with your favourite one.

Error [ERR_STREAM_CANNOT_PIPE]: Cannot pipe, not readable nodejs

function unzipCode() {
console.log('Unzipping contents...');
return new Promise((resolve, reject) => {
const files = [];
unzip.open(filePath, { autoclose: false, lazyEntries: true }, (err, zipfile) => {
if (err) reject;
zipfile.readEntry();
zipfile.on('entry', (entry) => {
if (!sourceDirectoryRegEx.test(entry.fileName)) {
console.log(" [X] Skipping: " + entry.fileName);
zipfile.readEntry();
}
else {
console.log(" [+] Unzipping: " + entry.fileName);
if (/\/$/.test(entry.fileName)) {
// directory file names end with '/'
mkdirp(path.join(cwd, entry.fileName), (err) => {
if (err) reject;
zipfile.readEntry();
});
}
else {
zipfile.openReadStream(entry, (err, readStream) => {
if (err) reject;
// ensure parent directory exists
mkdirp(path.join(cwd, path.dirname(entry.fileName)), (err) => {
if (err) reject;
let stream = fs.createWriteStream(path.join(cwd, entry.fileName));
readStream.pipe(stream, { end: false });
// console.log(readStream.pipe);
readStream.on('end', () => {
console.log('After write', entry.fileName);
// add file details to files array
files.push({
key: entry.fileName,
body: stream,
});
zipfile.readEntry();
readStream.unpipe(stream);
stream.end();
});
});
});
}
}
});
zipfile.once('end', () => {
zipfile.close();
resolve(files);
});
});
});
}
I am trying to unzip some files in aws-lambda console using the function. The enviornment I've chosen is nodejs 12.x. It was running with nodejs 8.10.
The exact error I'm encountering is Cannot pipe, not readable.
How to solve it?

Using nodejs archiver to download multiple google cloud storage files and zip them

I am trying to download files from google cloud storage and zip them.
async function makeZippedFiles(destination, all_file_links) {
console.log("In the zip file function");
for (let i in all_file_links) {
let name = all_file_links[i]['name']
let archive = archiver('zip', {
zlib: {level: 9} // Sets the compression level.
});
archive.on('error', function (err) {
throw err;
});
let output = fs.createWriteStream(__dirname + `/${name}.zip`);
console.log("loop number", i);
let sourceFile = all_file_links[i]['source'];
console.log(sourceFile, name);
let remoteFile = bucket.file(sourceFile);
let read_file = remoteFile.createReadStream();
await archive.append(read_file, {name: name});
read_file
.on('error', function (err) {
console.log(err);
})
.on('response', function (response) {
console.log("writing file", name);
// console.log(response);
// Server connected and responded with the specified status and headers.
})
.on('end', function () {
console.log("file downloaded", name);
// The file is fully downloaded.
})
archive.pipe(output);
archive.finalize();
}
}
In the example on top, I am looping through all files and creating individual archives. i.e., if I download two files, I would be creating two separate archives. This works.
However, if I want to zip all the files into one archive, I get the following error:
start of central directory not found; zipfile corrupt. (please
check that you have transferred or created the zipfile in the
appropriate BINARY mode and that you have compiled UnZip properly)
The code I used is:
async function makeZippedFiles(destination, all_file_links) {
console.log("In the zip file function");
let archive = archiver('zip', {
zlib: {level: 9} // Sets the compression level.
});
archive.on('error', function (err) {
throw err;
});
let output = fs.createWriteStream(__dirname + `/${destination}.zip`);
for (let i in all_file_links) {
let name = all_file_links[i]['name']
console.log("loop number", i);
let sourceFile = all_file_links[i]['source'];
console.log(sourceFile, name);
let remoteFile = bucket.file(sourceFile);
let read_file = remoteFile.createReadStream();
await archive.append(read_file, {name: name});
read_file
.on('error', function (err) {
console.log(err);
})
.on('response', function (response) {
console.log("writing file", name);
// console.log(response);
// Server connected and responded with the specified status and headers.
})
.on('end', function () {
console.log("file downloaded", name);
// The file is fully downloaded.
})
archive.pipe(output);
}
archive.finalize();
}
Found the solution. It was carelessness actually.
async function makeZippedFiles(destination, all_file_links) {
console.log("In the zip file function");
let archive = archiver('zip', {
zlib: {level: 9} // Sets the compression level.
});
archive.on('error', function (err) {
throw err;
});
let output = fs.createWriteStream(__dirname + `/${destination}.zip`);
archive.pipe(output);
for (let i in all_file_links) {
let name = all_file_links[i]['name']
console.log("loop number", i);
let sourceFile = all_file_links[i]['source'];
console.log(sourceFile, name);
let remoteFile = bucket.file(sourceFile);
let read_file = remoteFile.createReadStream();
await archive.append(read_file, {name: name});
read_file
.on('error', function (err) {
console.log(err);
})
.on('response', function (response) {
console.log("writing file", name);
// console.log(response);
// Server connected and responded with the specified status and headers.
})
.on('end', function () {
console.log("file downloaded", name);
// The file is fully downloaded.
})
}
archive.finalize();
}
I moved the archive.pipe(output) before the for loop and it works.

image is not getting uploaded through nodeJs

I am uploading an image from nodeJs.
Control is not getting into req.on('end'). Nothing is getting printed inside req.on('end'). I could not identify where is the problem. I am making an API and calling from js to upload an image in the server at a specific location.
app.post('/tde/api/photo/:widgetId/:choosenFileName',function(req,res){
console.log("In file Upload..");
console.log(req.params.widgetId);
console.log(req.params.choosenFileName);
res.writeHead(200, { 'Content-Type': 'application/binary' });
var filedata = '';
var chunks = [];
//req.setEncoding('binary');
req.on('data', function(chunk){
//filedata+= chunk;
chunks.push(chunk);
})
req.on('end', function (chunk) {
var dir = 'uploads/'+req.params.widgetId
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
console.log("directory created..");
}
fs.readdir(dir, function(err, filenames) {
if (err) {
onError(err);
return;
}
filenames.forEach(function(filename) {
console.log(filename);
fs.unlink(dir+'/'+filename, function(err) {
if (err) {
return console.error(err);
}
console.log("File deleted successfully!");
});
});
//fs.writeFile('uploads/'+req.params.widgetId+'/sanmoy.jpg', chunk, function(err) {
var fileName = req.params.choosenFileName;
var widgetId = req.params.widgetId;
//fs.writeFile('uploads/'+widgetId+'/'+fileName, filedata, 'binary', function(err) {
var buffer = Buffer.concat(chunks)
fs.writeFile('uploads/'+widgetId+'/'+fileName, buffer, function(err) {
if (err) {
return console.error(err);
}
console.log("writing file success!");
})
});
});
res.end("File is uploaded");
});

Resources