unzipping the file using cypress - javascript

I need to unzip the file using 'unzipping' whereas I am using the below code to do the same but it is partially unzipping but it is throwing an Invalid path error (as path contains special character *).please help me to fix it
let path = 'cypress/downloads/'
let file = '910-00001.1-20220419-1843.zip'
describe('example unzip', () => {
it(' test', () => {
cy.task('unzipping', { path, file })
})
//task code (Added it into plugins --> index.js)
const unzipping = require('./unzipping')
module.exports = (on, config) => {
on('task', {
'unzipping': unzipping.unzip,
})
}
// ./unzipping file (created a file named unzipping.js inside plugin folder)
const decompress = require('decompress');
const unzip = ({ path, file }) => decompress(path + file, path + 'unzip/' + file.replace('.zip', ''))
module.exports = {
    unzip,
}

So, I tried all your code you gave above, and it worked perfectly.
The only thing I can think if is the contents of the zip is the problem. In my test I made a simple zip with two text files 1.txt and 2.txt, then running the test, found them in the folder /cypress/downloads/unzip/910-00001.1-20220419-1843.
I suggest you do the same with a dummy zip, if the code works then look at the contents of 910-00001.1-20220419-1843.zip.

Related

Adding files into a gulp stream during the pipeline

I've got a gulp stream that reads a few hundred markdown files and runs through a series of pipes like so:
var mystream = src('app/pages/**/*.md')
.pipe(frontMatter({
property: 'fm',
remove: true
}))
.pipe(data(function (file) {
if (file.fm.title) file.fm.title_html = markdown.marked.parseInline(file.fm.title)
if (file.fm.description) file.fm.description_html = markdown.marked(file.fm.description)
}))
.pipe(data(process_last_update))
....and like 10 more pipes writing the stream at the end....
.pipe(dest('site'))
This all works. What I'm trying to do is during one of those pipe stages, I'm checking the markdown files frontmatter and if it has a certain value (array of strings), then I want to duplicate the file setting the path to what it finds in the frontmatter and add them to the stream.
This is the code I'm trying:
.pipe(data(function (file) {
if (file.fm.slug_history) {
file.fm.slug_history.forEach(slug => {
let newfile = Object.assign({}, file);
newfile.path = file.base + "/" + slug + "/index.html";
mystream.write(newfile);
})
}
}))
But the .pipe(dest('site')) at the end just isn't writing the additional files I've seemingly added to the stream. Any idea what I'm doing wrong?

folders and files are not visible after uploading file though multer

I am working on a small project. discussing Step by step
At first I am uploading zip files though multer
extracting those files (How can I call extract function after completing upload using multer?)
After extracting those I am trying to filter those files
after filtering those files I want to move some files to another directory
in my main index.js I have
A simple route to upload files which is working
// MAIN API ENDPOINT
app.post("/api/zip-upload", upload, async (req, res, next) => {
console.log("FIles - ", req.files);
});
Continuous checking for if there is any zip file that needs to unzip but the problem is after uploading it's not showing any files or dir
// UNZIP FILES
const dir = `${__dirname}/uploads`;
const files = fs.readdirSync("./uploads");
const filesUnzip = async () => {
try {
if (fs.existsSync(dir)) {
console.log("files - ", files);
for (const file of files) {
console.log("file - ", file);
try {
const extracted = await extract("./uploads/" + file, { dir: __dirname + "/uploads/" });
console.log("Extracted - ",extracted);
// const directories = await fs.statSync(dir + '/' + file).isDirectory();
} catch (bufErr) {
// console.log("------------");
console.log(bufErr.syscall);
}
};
// const directories = await files.filter(function (file) { return fs.statSync(dir + '/' + file).isDirectory(); });
// console.log(directories);
}
} catch (err) {
console.log(err);
}
return;
}
setInterval(() => {
filesUnzip();
}, 2000);
Moving files to static directory but here is the same problem no directory found
const getAllDirs = async () => {
// console.log(fs.existsSync(dir));
// FIND ALL DIRECTORIES
if (fs.existsSync(dir)) {
const directories = await files.filter(function (file) { return fs.statSync(dir + '/' + file).isDirectory(); });
console.log("Directories - ",directories);
if (directories.length > 0) {
for (let d of directories) {
const subdirFiles = fs.readdirSync("./uploads/" + d);
for (let s of subdirFiles) {
if (s.toString().match(/\.xml$/gm) || s.toString().match(/\.xml$/gm) !== null) {
console.log("-- ", d + "/" + s);
const move = await fs.rename("uploads/" + d + "/" + s, __dirname + "/static/" + s, (err) => { console.log(err) });
console.log("Move - ", move);
}
}
}
}
}
}
setInterval(getAllDirs, 3000);
There are so many issues with your code, I don't know where to begin:
Why are you using fs.xxxSync() methods if all your functions are async? Using xxxSync() methods is highly discouraged because it's blocking the server (ie parallel requests can't/won't be accepted while a sync reading is in progress). The fs module supports a promise api ...
Your "Continuous checking" for new files is always checking the same (probably empty) files array because it seems you are executing files = fs.readdirSync("./uploads"); only once (probably at server start, but I can't tell for sure because there isn't any context for that snippet)
You shouldn't be polling that "uploads" directory. Because as writing a file (if done properly) is an asynchronous process, you may end up reading incomplete files. Instead you should trigger the unzipping from your endpoint handler. Once it is hit, body.files contains the files that have been uploaded. So you can simply use this array to start any further processing instead of frequently polling a directory.
At some points you are using the callback version of the fs API (for instance fs.rename(). You cannot await a function that expects a callback. Again, use the promise api of fs.
EDIT
So I'm trying to address your issues. Maybe I can't solve all of them because of missing infomation, but you should get the general idea.
First of all, you shuld use the promise api of the fs module. And also for path manipulation, you should use the available path module, which will take care of some os specific issues.
const fs = require('fs').promises;
const path = require('path');
Your API endpoint isn't currently returning anything. I suppose you stripped away some code, but still. Furthermore, you should trigger your filehandling from here, so you don't have to do directory polling, which is
error prone,
wasting resources and
if you do it synchronously like you do blocks the server
app.post("/api/zip-upload", upload, async (req, res, next) => {
console.log("FIles - ", req.files);
//if you want to return the result only after the files have been
//processed use await
await handleFiles(req.files);
//if you want to return to the client immediately and process files
//skip the await
//handleFiles(req.files);
res.sendStatus(200);
});
Handling the files seems to consist of two different steps:
unzipping the uploaded zip files
copying some of the extracted files into another directory
const source = path.join(".", "uploads");
const target = path.join(__dirname, "uploads");
const statics = path.join(__dirname, "statics");
const handleFiles = async (files) => {
//a random folder, which will be unique for this upload request
const tmpfolder = path.join(target, `tmp_${new Date().getTime()}`);
//create this folder
await fs.mkdir(tmpfolder, {recursive: true});
//extract all uploaded files to the folder
//this will wait for a list of promises and resolve once all of them resolved,
await Promise.all(files.map(f => extract(path.join(source, f), { dir: tmpfolder })));
await copyFiles(tmpfolder);
//you probably should delete the uploaded zipfiles and the tempfolder
//after they have been handled
await Promise.all(files.map(f => fs.unlink(path.join(source, f))));
await fs.rmdir(tmpfolder, { recursive: true});
}
const copyFiles = async (tmpfolder) => {
//get all files/directory names in the tmpfolder
const allfiles = await fs.readdir(tmpfolder);
//get their stats
const stats = await Promise.all(allfiles.map(f => fs.stat(path.join(tmpfolder, f))));
//filter directories only
const dirs = allfiles.filter((_, i) => stats[i].isDirectory());
for (let d of dirs) {
//read all filenames in the subdirectory
const files = await fs.readdir(path.join(tmpfolder, d)));
//filter by extension .xml
const xml = files.filter(x => path.extname(x) === ".xml");
//move all xml files
await Promise.all(xml.map(f => fs.rename(path.join(tmpfolder, d, f), path.join(statics, f))));
}
}
That should do the trick. Of course you may notice there is no error handling with this code. You should add that.
And I'm not 100% sure about your paths. You should consider the following
./uploads refers to a directory uploads in the current working directory (whereever that may be)
${__dirname}/uploads refers to a directory uploads which is in the same directory as the script file currently executing Not sure if that is the directory you want ...
./uploads and ${__dirname}/uploads may point to the same folder or to completely different folders. No way knowing that without additional context.
Furthermore in your code you extract the ZIP files from ./uploads to ${__dirname}/uploads and then later try to copy XML files from ./uploads/xxx to ${__dirname}/statics, but there won't be any directory xxx in ./uploads because you extracted the ZIP file to a (probably) completely different folder.

Why does my async not work well with the third call but perfect with the first two

So I have a mind boggler, my app grabs a git repo (simple-git) then makes an npm i on the files inside (shelljs) and then zips using archiver. Of course it needs to be async but the first part and second part work however at the point of archiving it fails (the next step is for axios to await the zip being done), also before this when I ran the zip code with the grabbing repo code it would create the zip file in the correct root directory but now does it in the folder directory instead (repo/folder) , the zip is empty now though instead of zipping the other contents. Please assist if you can
The code:
// // //Make call
function makeCall() {
return new Promise((resolve) => {
resolve(
git()
.silent(true)
.clone(remote, ["-b", branch])
.then(() => console.log("finished"))
.catch((err) => console.error("failed: ", err))
);
});
}
//Make NPM Modules
async function makeModules() {
await makeCall();
const pathOfFolder = path.join(__dirname, "folder/sub");
shell.cd(pathOfFolder)
return new Promise((resolve) => {
resolve(
shell.exec("npm i"));
});
}
async function makeZip() {
await makeModules();
const output = fs.createWriteStream(`${branch}.zip`);
const archive = archiver("zip");
output.on("close", function () {
console.log(archive.pointer() + " total bytes");
console.log(
"archiver has been finalized and the output file descriptor has closed."
);
});
archive.pipe(output);
// append files from a sub-directory, putting its contents at the root of archive
archive.directory("folder", false);
// append files from a sub-directory and naming it `new-subdir` within the archive
archive.directory("subdir/", "new-subdir");
archive.finalize();
}
makeZip();
Resolved it, moved to other files and set path correctly

How to check if path is file or directory

Is there any clean way to check if a path is a file or directory?
Currently I am using this:
exports.isDirectory = (dirPath) => {
return fs.lstatSync(dirPath).isDirectory()
}
But my problem here is that if dirPath does not exist yet, then lstatSync gives out an error.
Then I also tried:
exports.getFileName = (filePath) => {
return filePath.split(/[\\\/]/).pop()
}
exports.isDirectory = (dirPath) => {
return exports.getFileName(dirPath) === ''
}
And call:
const home = require('os').homedir()
const sampleLoc = path.join(home, '/.folder/another'))
isDirectory(sampleLoc)
But it only basically thinks another is the filename and returns false on isDirectory.
Can't really check for the presence of . (like an extension of a file name) since my folders can have dots anywhere on its name.
How can I check if the given path is for a file or directory? (considering it does not exist yet at the point of checking)?
Help!

How to properly read all file types with react js and add to IPFS in browser

enter image description here
I am trying to read a file (which can be anything like video, image , text ) with react .
I want to add data in the IPFS through Node JS. In normal case(which means when i m only writing in js) I would do it like this :
const data = await fs.readFile(file_path)
console.log(data)
const filesAdded = await nodeDialer.add({
path:file_path,
content:data,
})
console.log(filesAdded)
THe files would be added easily(any type of file).
I tried fs and found out it only works in the node side not on the react side.
and whereever i looked they were using some readastext functions for .txt file or .csv file.
So a proper solution, I couldn't find.
I solved it with this:
Created a event handler for file upload :
captureFile(event){
const file = event.target.files[0]
this.setState({ file_path : file})
console.log('--------------', this.state.file_path)
const reader = new window.FileReader()
reader.readAsArrayBuffer(file)
reader.onloadend = () => {
this.setState({ buffer: Buffer(reader.result) })
console.log('buffer --- ', this.state.buffer)
console.log('path --- ', this.state.file_path.name)
}
}
then I add the file in IPFS with :
const filesAdded = await node.add({
path: this.state.file_path.name ,
content:this.state.buffer
})

Categories