Problem with traversing file system using Node.js - node.js

I keep getting the error 'Error: ENOENT: no such file or directory, open 't1.txt''
when I run the function starting in the top-level directory pictured below.
I think it has to with 'fs.readFileSync()' attempting to read a file's contents from a directory different than the one fs is declared in, though I am not quite sure.
Picture of directory structure
/* the built-in Node.js 'fs' module is included in our program so we can work with the computer's file system */
const fs = require('fs');
// used to store the file contents of the files encountered
const fileContents = {};
/* stores the duplicate files as subarrays within the array, where the first element of the subarray is the duplicate file, and the second element is the original */
let duplicateFiles = [];
const traverseFileSystem = function (currentPath) {
// reads the contents of the current directory and returns them in an array
let files = fs.readdirSync(currentPath);
// for-in loop is used to iterate over contents of directory
for (let i in files) {
let currentFile = currentPath + '/' + files[i];
// retrieves the stats of the current file and assigns them to a variable
let stats = fs.statSync(currentFile);
// it's determined if the 'currentFile' is actually a file
if (stats.isFile()) {
/* if the file's contents are in the 'fileContents' object, then a new file has been encountered */
if(fileContents[fs.readFileSync(files[i])] === undefined) {
// the file's contents are set as the key, and the file path as the value
fileContents[fs.readFileSync(files[i])] = currentFile;
}
// otherwise, the file's contents already exist in the 'fileContents' object, which means a duplicate file has been found
else {
duplicateFiles.push([fileContents[fs.readFileSync(files[i])], currentFile]);
}
}
/* if the 'file' is actually a directory, traverseFileSystem() is called recursively on that directory */
else if (stats.isDirectory()) {
traverseFileSystem(currentFile);
}
}
return duplicateFiles;
};

You have fs.readFileSync(files[i]) which should be fs.readFileSync(currentFile) based on your code. Haven't confirmed your logic, but this should solve the error you are currently getting.

Related

How to edit this code to wait for a file fully uploaded with node.js?

Hi I am trying to download a file and when it downloads it first has the extension .tmp or .crdownload, then after it is fully downloaded the extension changes to whatever the correct extension is, for example .png. I want to wait until the file no longer has the extension .tmp or .crdownload and then save the new file path to a variable. How can I do this? I have looked here on Stack Overflow but it is not answering all my questions. This is a unique and specific question. That is what I have so far. I don't mind if you don't use this code as long as the resulting code waits for the extension to change and saves the path to a variable as a string.
Code:
var downloadanduploadpath = "C:/Users/user1/Downloads";
//ptc mean path to check. have differnt name so the variable name of the placeholder in the function call is not the same name as the variable name in the function
var ptc = downloadanduploadpath;
var pathtocheck = ptc;
var timetowaitforimagefiledownloaded = 5000;
var fs = require('fs');
//let dirToCheck = pathtocheck;
var filecheckerfiles = fs.readdirSync(pathtocheck);
var filecheckerlatestPath = `${pathtocheck}/${filecheckerfiles[0]}`;
var filecheckerlatestTimeStamp = fs.statSync(filecheckerlatestPath).mtime.getTime();
filecheckerfiles.forEach(filecheckerfile => {
var filecheckerpath = `${pathtocheck}/${filecheckerfile}`;
var filecheckertimeStamp = fs.statSync(filecheckerpath).mtime.getTime();
if (filecheckertimeStamp > filecheckerlatestTimeStamp) {
filecheckerlatestTimeStamp = filecheckertimeStamp;
lastdownloadedimagetimestamp = filecheckerlatestTimeStamp;
lastdownloadedimage = filecheckerpath;
}
});
//get the extention of the last downloaded image
var lastdownloadedimageextention = lastdownloadedimage.split(".").pop();
//"png" || "jpg" || "jpeg" || "gif" ||
//if the file is a .tmp the image is not fully downloaded. run code inside to wait for it to not be a tmp file showing that the image if fully downloaded
if((lastdownloadedimageextention == "tmp") || (lastdownloadedimageextention == "crdownload") ){
//Show the file path to the console
console.log(lastdownloadedimage);
//show file not fill downloaded message in console
console.log("Image not yet fully downloaded.");
//show preparing to wait message in console
console.log("Preparing to wait for full download.");
//get all the files in the folder directory/path
var filecheckerfindpathbytimestamp = fs.readdirSync(pathtocheck);
console.log("hi1");
//define variable to store the path of the last donwloaded image foudn by timestamp
var lastdownloadedimagefoundbytimestamppath;
console.log("hi2");
//use the timestamp as an index to get the last downloaded file and then check the file at this timestamp(the last downloaded image) and check its file path.
//using the timestamp as an image lets us check the file without using the name because the name changes from .tmp to .png for example, so we are unable to get the
//the file by its name because of this name , so we use the timestamp to specifc the file we want to check the extention of instead
//find path of the last downloaded file by using the time to find it
filecheckerfindpathbytimestamp.forEach(filecheckerfindpathbytimestampfile => {
var filecheckerfindpathbytimestamppath = `${pathtocheck}/${filecheckerfindpathbytimestampfile}`;
console.log("hi3");
var filecheckerfindpathbytimestamptimeStamp = fs.statSync(filecheckerfindpathbytimestamppath).mtime.getTime();
console.log("hi4");
if (filecheckerfindpathbytimestamptimeStamp == lastdownloadedimagetimestamp) {
console.log("hi5");
lastdownloadedimagefoundbytimestamppath = filecheckerfindpathbytimestamppath;
console.log("hi6");
}
});
console.log("hi7");
//keep checking the file that ends in .tmp untill it changes from .tmp . once the file is no longer endng in .tmp indicating that the file is
//fully downloaded this path that is looking for the fiel path including the .tmp will no longer be valid because of the file path becomeing .png for example
// that it has fully downloaded, and the file path will not return true because it is no longer valid with the .tmp extention.
//once this path is no longer valid we will know that the file has fully downloaded because that path no longer ends in .tmp. We can then end the while loop.
//because file if fully downloaded.
//
while(fs.existsSync(lastdownloadedimagefoundbytimestamppath) == true){
//while((fs.existsSync(lastdownloadedimage)) == true){
//Show the file path to the console
console.log(lastdownloadedimage);
//Wait code
//Wait on the image converting page
await page2.type('.jsoninputtextarea', " ", {delay:timetowaitforimagefiledownloaded});
//show waiting for file fully download message in console
console.log("Waiting for image to fully download.");
}
//create varaible to find path of the last downloaded file by using the time to find it now that it is fully downloaded
var filecheckerfindfullydownloadedfiletimestamp = fs.readdirSync(pathtocheck);
//find path of the last downloaded file by using the time to find it now that it is fully downloaded
filecheckerfindfullydownloadedfiletimestamp.forEach(filecheckerfindfullydownloadedfilefile => {
var filecheckerfindfullydownloadedfilepath = `${pathtocheck}/${filecheckerfindfullydownloadedfilefile}`;
console.log("hi8");
var filecheckerfindfullydownloadedfiletimeStamp = fs.statSync(filecheckerfindfullydownloadedfilepath).mtime.getTime();
console.log("hi9");
if (filecheckerfindfullydownloadedfiletimeStamp == lastdownloadedimagetimestamp) {
console.log("hi10");
lastdownloadedimagefoundbytimestamppath = filecheckerfindfullydownloadedfilepath;
console.log("hi11");
}
});
console.log("hi12");
//Set lastdownloaded image to the path the now ends in the file extention (example .png) now instead of .tmp
//
lastdownloadedimage = lastdownloadedimagefoundbytimestamppath;
}
//Remove the path the of the image so we only have image name and file type
//Before: C:/Users/edtec/Downloads/image.png After: image.png
lastdownloadedimage = lastdownloadedimage.replace(downloadanduploadpath, "");
//Return lastdownloadedimage
//return lastdownloadedimage;
//}
//lastdownloadedimage = getlastdownloadedimage(downloadanduploadpath);
//console.log(lastdownloadedimage);
console.log(lastdownloadedimage);

How do you get a list of the names of all files present in a web server directory using Node.js?

when using fs.readdir it gives me file name present in the given path but how can get file name stored on a specific path on a web server.
I believe you are using this function
fs.readdir ('../', function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
To access the
root(or C drive) use / .
current directory use ./.
parent directory use ../.
parent of parent directory use ../../.
To access a directory in the parent directory use ../sibling_name.
Now I believe you can navigate through directories. Navigate through directories and list the files and the folders contained in the directory.
I think it will help u.
const fs = require('fs');
const path = require('path');
function getFile(dirPath) {
const files = fs.readdirSync(dirPath);
files.forEach(function (item) {
const currentPath = path.join(dirPath, item),
isFile = fs.statSync(currentPath).isFile(),
isDir = fs.statSync(currentPath).isDirectory();
if (isFile) {
// console.log(currentPath);
} else if (isDir) {
console.log(currentPath);
getFile(currentPath);
}
});
}
getFile('./'); // this is your server path

readdirSync cannot read encrypted home folder when accessing it directly

const fs = require("fs")
//const HOW = "/home/test/everything"
// const HOW = "/home/test/"
// This one fails. My home is encrypted and it cannot read directories, it gets the .Private file. I want to read files and directories in my home folder. But can't.
const HOW = "/home/test/folder/"
// This one works for some reason. It lists all the directories in the folder.
// const HOW = "folder"
// This one works as well
var list = walk(HOW)
console.log(list)
// How do I get contents of /home/test (which happens to be my home folder).
// I'm both root and "test" user of the computer.
I'd like to have walk() work on /home/test/.
The code that fails:
var walk = function(dir) {
var results = []
var list = fs.readdirSync(dir)
list.forEach(function(file) {
file = dir + '/' + file
var stat = fs.statSync(file)
if (stat && stat.isDirectory()) results = results.concat(walk(file))
else results.push(file)
})
return results
}
The exact line causing it (stack trace): var stat = fs.statSync(file)
The error is:
Error: ENOENT: no such file or directory, stat '/home/test/.Private/###############################################################'
Where # is an amount of letters whose importance to safety is unknown to me.
Node.js doesn't have a problem addressing any folder contained within my home folder, but cannot address the home folder itself. Neither my own account nor root account can get access to it.
I think you are adding an unnecessary /. Try changing
const HOW = "/home/test/folder/"
to
const HOW = "/home/test/folder"

Rename files inside zip archive in nodejs

I am writing a nodejs script which should do the following:
Download a zip file
Remove the top level directory of the zip file (moving all files one folder up)
Upload the new zip file
Because the zip file is rather large, I would like to rename (or move) the files without unzipping and rezipping the file.
Is that possible?
Yes, it's possible
Using a library like adm-zip
var AdmZip = require('adm-zip');
//create a zip object to hold the new zip files
var newZip = new AdmZip();
// reading archives
var zip = new AdmZip('somePath/download.zip');
var zipEntries = zip.getEntries(); // an array of ZipEntry records
zipEntries.forEach(function(zipEntry) {
var fileName = zipEntry.entryName;
var fileContent = zip.readAsText(fileName)
//Here remove the top level directory
var newFileName = fileName.substring(fileName.indexOf("/") + 1);
newZip.addFile(newFileName, fileContent, '', 0644 << 16);
});
newZip.writeZip('somePath/upload.zip'); //write the new zip
Algorithm
Create a newZip object to temporarily hold files in memory
Read all entries in the downloaded zip. For each entry
Read the fileName. This includes the path
Read the file content using the fileName
Remove the top level directory name to get the newFileName
Add the fileContent in step 2 to the newZip giving it the newFileName from step 3
Finally, write out the newZip to disk giving it a new zipName
Hope that helps
You can use the great jszip library with async-promise style.
import jszip from 'jszip';
import fs from 'fs';
/**
* Move/rename entire directory tree within a zip.
* #param {*} zipFilePath The original zip file
* #param {*} modifiedZipFilePath The path where palace the modified zip
* #param {*} originalDir The original directory to change
* #param {*} destinationDir The new directory to move to.
*/
async function moveDirectory(zipFilePath, modifiedZipFilePath, originalDir, destinationDir) {
// Read zip file bits buffer
const zipFileBuffer = await fs.promises.readFile(zipFilePath);
// Load jszip instance
const zipFile = await jszip.loadAsync(zipFileBuffer);
// Get the original directory entry
const originalDirContent = zipFile.folder(originalDir);
// Walk on all directory tree
originalDirContent.forEach((path, entry) => {
// If it's a directory entry ignore it.
if (entry.dir) {
return;
}
// Extract the file path within the directory tree
const internalDir = path.split(originalDir)[0];
// Build the new file directory in the new tree
const newFileDir = `${destinationDir}/${internalDir}`;
// Put the file in the new tree, with the same properties
zipFile.file(newFileDir, entry.nodeStream(), {
createFolders: true,
unixPermissions: entry.unixPermissions,
comment: entry.comment,
date: entry.date,
});
});
// After all files copied to the new tree, remove the original directory tree.
zipFile.remove(originalDir);
// Generate the new zip buffer
const modifiedZipBuffer = await zipFile.generateAsync({ type: 'nodebuffer' });
// Save the buffer as a new zip file
await fs.promises.writeFile(modifiedZipFilePath, modifiedZipBuffer);
}
moveDirectory('archive.zip', 'modified.zip', 'some-dir/from-dir', 'some-other-dir/to-dir');
This is simply walking on all original directory tree entries and place them in the new directory tree.

Check uploaded file extension in Sails js

How we can check uploaded file extension in sails js?
I tried on skipper and multer but have no result.
any suggestion?
You should use saveAs options for each file before saving.
var md5 = require('md5');
module.exports = {
testUpload:function(req,res){
// setting allowed file types
var allowedTypes = ['image/jpeg', 'image/png'];
// skipper default upload directory .tmp/uploads/
var allowedDir = "../../assets/images";
// don not define dirname , use default path
req.file("uploadFiles").upload({
saveAs:function(file, cb) {
var d = new Date();
var extension = file.filename.split('.').pop();
// generating unique filename with extension
var uuid=md5(d.getMilliseconds())+"."+ extension;
// seperate allowed and disallowed file types
if(allowedTypes.indexOf(file.headers['content-type']) === -1) {
// save as disallowed files default upload path
cb(null,uuid);
}else{
// save as allowed files
cb(null,allowedDir+"/"+uuid);
}
}
},function whenDone(err,files){
return res.json({
files:files,
err:err
});
});
}
}
Just get uploaded files array and check last chunk of string after dot.
req.file('file').upload({
maxBytes: 2000000,
dirname: 'uploadFolder'
}, function (error, files) {
if (error) return sails.log.error(error);
// You have files array, so you can do this
files[0].fd.split('.').pop(); // You get extension
}
What is going on here? When upload is finished you will get array of files with their filenames. You can get data from that array and see where this file is located (full path).
The last thing is splitting string by dots and get last item from the array with pop() method.

Resources