Vue/Electron/Webpack Cannot find image module after mutating image path - javascript

I'm using Vue CLI 4.4.6 w/ Electron & Webpack and am running into an issue with Webpack telling me "cannot find module './SOME PORTION OF THE IMAGE LOCATION' when trying to programmatically move an image between the local folder and submitted folder.
My directory structure is as follows:
/src
/resources
/images
/local
/SUB-DIRECTORIES
imageBefore.png
/submitted
/SUB-DIRECTORIES
imageAfter.png
This problem only occurs after I run the uploadImage method shown below:
computed: {
imagePath: function() {
let loc = this.image.upload_progress === 'submit'? 'submitted' : 'local'
let filepath = path.join(loc,this.image.path);
return require('../resources/images/' + filepath);
}
},
methods: {
uploadImage(){
// push new image to global xylarium
const destinationPath = (process.env.IS_PRODUCTION === 'true') ? `${process.env.RESOURCES_PATH}/images` : `src/resources/images/submitted/${this.image.path}`;
const currentPath = (process.env.IS_PRODUCTION === 'true') ? `${process.env.RESOURCES_PATH}/images` : `src/resources/images/local/${this.image.path}`;
if(this.state != 'submit' && fs.existsSync(currentPath)) {
fs.rename(currentPath, destinationPath, async (err) => {
if(err) {
this.errorMessage = err;
this.showError = true;
throw(err);
} else {
// update uploadStatus var
await this.$store.dispatch('updateImageStatus', {id: this.image.uuid, code: 'submit'});
console.log('Successfully moved file');
// Update user on image status
this.showSnackBar = true;
}
})
} else {
this.errorMessage = 'The image could not be found. Make sure that the image exists in the original folder.';
this.showError = true;
}
}
}
<zoom-on-hover class="camWindow" :img-normal="imagePath" :scale="2"></zoom-on-hover>
These images can't go in the public folder as they aren't static and load properly when the page does. This error is only thrown when I attempt to run the uploadImage method. Has anyone run into this problem and if so, how did you fix it?
Thanks in advance.

Related

How could I check If a zip file is corrupted in NodeJS?

I would check if a ZIP file is corrupted using NodeJS using less CPU and memory as possible.
How to corrupt a ZIP file:
Download a ZIP file
Open the ZIP file using a text editor optimized like Notepad++
Rewrite the header. Only put random characters.
I am trying to reach this goal using the NPM library "node-stream-zip"
private async assertZipFileIntegrity(path: string) {
try {
const zip = new StreamZip.async({ file: path });
const stm = await zip.stream(path);
stm.pipe(process.stdout);
stm.on('end', () => zip.close());
} catch (error) {
throw new Error();
}
}
However, when I run the unit tests I receive an error inside an array:
Rejected to value: [Error]
import zip from 'yauzl';
import path from 'path';
const invalidZipPath = path.resolve('invalid.zip');
const validZipPath = path.resolve('valid.zip');
const isValidZipFile = (filePath) => {
return zip.open(filePath, { lazyEntries: true }, (err, stream ) => {
if (err) {
console.log('fail to read ', filePath);
return false;
}
console.log('success read ', filePath);
return true;
});
}
isValidZipFile(validZipPath);
isValidZipFile(invalidZipPath);

Error: ENOTDIR: not a directory, scandir error on interactionCreate

All of my files from Commands are read in fine but I get an error from 'interactionCreate.jslocated inEvents`
node:internal/fs/utils:343
throw err;
^
Error: ENOTDIR: not a directory, scandir './Events/interactionCreate.js'
My Event.js file is as follows:
const { readdirSync } = require('fs');
const ascii = require('ascii-table');
let table = new ascii("Events");
table.setHeading('EVENTS', ' LOAD STATUS');
module.exports = (client) => {
readdirSync('./Events/').forEach(dir => {
const events = readdirSync(`./Events/${dir}`).filter(file => file.endsWith('.js'));
for(let file of events) {
let pull = require(`../Events/${dir}/${file}`);
if(pull.name) {
client.events.set(pull.name, pull);
} else {
table.addRow(file, 'EVENT REGISTERED')
continue;
} if(pull.aliases && Array.isArray(pull.aliases)) pull.aliases.forEach(alias => client.aliases.set(alias, pull.name))
}
});
console.log(table.toString());
}
Your problem is here:
readdirSync('./Events/').forEach(dir => {
const events = readdirSync(`./Events/${dir}`)
readdirSync will return all the entries in the Events dir, that includes both files and directories. You've named your variable dir but they aren't all dirs. This is evidenced by the error message which specifically states ./Events/interactionCreate.js is not a directory.
Either remove non-dirs from your Events directory (i.e. move that file), or better, check if dir is in fact a directory before calling readdirSync on it.
The easiest way to do that is to add the {withFileTypes: true} option, and then you can call dir.isDirectory()
See docs https://nodejs.org/api/fs.html#fsreaddirsyncpath-options

How would I go about waiting for a child process to finish before telling Node.js to continue executing code?

So I am building an Electron and React App. I am using ghost-script to create imgs of certain pdf files and I want to know how I would tell Node.js to wait for the imgs to be created before bringing up the window and changing the state in the App. These imgs are being used as src for a component and when the component tries to load the img it somewhat retains a broken state because the img src doesn't exist when the state updates.
// this is where I set the state before sending all the data to the renderer process(the front end of the App)
function getStateReady(theState, event) {
let pdfFiles = scanDirectory(currentDir);
let pdfNames = getPdfName(pdfFiles);
imageUrls = getImgName(pdfFiles);
console.log(imageUrls);
createImg(pdfFiles, pdfNames);
switch (theState) {
case 'initialState':
mainWindow.webContents.on('did-finish-load', () => {
mainWindow.webContents.send('initialState', pdfFiles, imageUrls);
})
break;
case 'secondState-reply':
event.sender.send('secondState-reply', pdfFiles, imageUrls);
break;
default:
console.log('a param was missing');
}
}
//these to functions take a pdf file path and its name to create an img
function createImg(pdfPaths, pdfNames) {
pdfNames.forEach((item, index) => {
if(fs.existsSync(path.join(rootDirectory, 'src', 'imgs', item.replace('.pdf', '.jpg')))) {
console.log('image exists');
}
else {
console.log("creating image");
child(returnProcess(pdfPaths[index], item), (err, stdout) => {
if(err) {
console.log(err)
}
console.log(stdout)
})
}
})
}
function returnProcess(pdfPath, pdfName) {
let newPdf = `"${pdfPath}"`
let output = `"${path.join(rootDirectory, 'src', 'imgs', pdfName.replace('.pdf', '.jpg'))}"`;
let mainProcess = `"C:\\Program Files\\gs\\gs9.23\\bin\\gswin64c.exe" -q -o ${output} -sDEVICE=pngalpha -dLastPage=1 ${newPdf}`
return mainProcess;
}
I am not completely sure with code and logic and I have never worked with ghost-script but what I can suggest here to solve this issue is use a call back function. basically pass a callback function to createImg method and execute the callback function which will tell the NodeJS that process is done and front-end should able to display the created image.
Below is the update code.
// this is where I set the state before sending all the data to the renderer process(the front end of the App)
function getStateReady(theState, event) {
let pdfFiles = scanDirectory(currentDir);
let pdfNames = getPdfName(pdfFiles);
imageUrls = getImgName(pdfFiles);
console.log(imageUrls);
createImg(pdfFiles, pdfNames, function (){
switch (theState) {
case 'initialState':
mainWindow.webContents.on('did-finish-load', () => {
mainWindow.webContents.send('initialState', pdfFiles, imageUrls);
})
break;
case 'secondState-reply':
event.sender.send('secondState-reply', pdfFiles, imageUrls);
break;
default:
console.log('a param was missing');
}
});
}
//these to functions take a pdf file path and its name to create an img
function createImg(pdfPaths, pdfNames, fun) {
pdfNames.forEach((item, index) => {
if(fs.existsSync(path.join(rootDirectory, 'src', 'imgs', item.replace('.pdf', '.jpg')))) {
console.log('image exists');
}
else {
console.log("creating image");
child(returnProcess(pdfPaths[index], item), (err, stdout) => {
if(err) {
console.log(err)
}
console.log(stdout)
})
}
})
// call the callback function
fun.call();
}
function returnProcess(pdfPath, pdfName) {
let newPdf = `"${pdfPath}"`
let output = `"${path.join(rootDirectory, 'src', 'imgs', pdfName.replace('.pdf', '.jpg'))}"`;
let mainProcess = `"C:\\Program Files\\gs\\gs9.23\\bin\\gswin64c.exe" -q -o ${output} -sDEVICE=pngalpha -dLastPage=1 ${newPdf}`
return mainProcess;
}

How to show an open file native dialog with Electron?

I am trying to add functionality to my Electron app that will allow users to open a file in the app, specifically plain text files. After looking at the Electron documentation, I found this page. I added this code to my app.js file, which I linked to in my index.html.
var fs = require('fs');
var dialog = require('electron');
$openFile = $('#openBtn');
$editor = $('#editor');
$openFile.click(function(){
dialog.showOpenDialog(function(fileNames) {
if (fileNames === undefined) return;
var fileName = fileNames[0];
fs.readFile(fileName, 'utf-8', function (err, data) {
$editor.val(data);
});
});
});
However, when I run this, this error shows up in the console: Uncaught TypeError: dialog.showOpenDialog is not a function I have tried using remote, but to no avail.
Has anyone know how to fix this problem?
Thanks in advance
const {dialog} = require('electron').remote;
document.querySelector('#selectBtn').addEventListener('click', function (event) {
dialog.showOpenDialog({
properties: ['openFile', 'multiSelections']
}, function (files) {
if (files !== undefined) {
// handle files
}
});
});
On the main process you can use
const {dialog} = require('electron');
dialog.showOpenDialog({properties: ['openFile'] }).then(function (response) {
if (!response.canceled) {
// handle fully qualified file name
console.log(response.filePaths[0]);
} else {
console.log("no file selected");
}
});
response looks like:
{
canceled: false,
filePaths: [
'<fullpath>/<filename>'
]
}

Node.js read a file in a zip without unzipping it

I have a zip file (actually it's an epub file) I need to loop through the files in it and read them without unzipping them to the disk.
I tried to use a Node.js library called JSZip but the content of each file is stored in memory in Buffer and whenever I try to decode the buffer content to string the content returned is unreadable
Here's the code I tried:
const zip = new JSZip();
// read a zip file
fs.readFile(epubFile, function (err, data) {
if (err) throw err;
zip.loadAsync(data).then(function (zip) {
async.eachOf(zip.files, function (content, fileName, callback) {
if (fileName.match(/json/)) {
var buf = content._data.compressedContent;
console.log(fileName);
console.log((new Buffer(buf)).toString('utf-8'));
}
callback();
}, function (err) {
if (err) {
console.log(err);
}
});
});
});
Since unzip seems to be abandoned, I used node-stream-zip with pretty good success.
npm install node-stream-zip
Reading files be all like:
const StreamZip = require('node-stream-zip');
const zip = new StreamZip({
file: 'archive.zip',
storeEntries: true
});
zip.on('ready', () => {
// Take a look at the files
console.log('Entries read: ' + zip.entriesCount);
for (const entry of Object.values(zip.entries())) {
const desc = entry.isDirectory ? 'directory' : `${entry.size} bytes`;
console.log(`Entry ${entry.name}: ${desc}`);
}
// Read a file in memory
let zipDotTxtContents = zip.entryDataSync('path/inside/zip.txt').toString('utf8');
console.log("The content of path/inside/zip.txt is: " + zipDotTxtContents);
// Do not forget to close the file once you're done
zip.close()
});
npm install unzip
https://www.npmjs.com/package/unzip
fs.createReadStream('path/to/archive.zip')
.pipe(unzip.Parse())
.on('entry', function (entry) {
var fileName = entry.path;
var type = entry.type; // 'Directory' or 'File'
var size = entry.size;
if (fileName === "this IS the file I'm looking for") {
entry.pipe(fs.createWriteStream('output/path'));
} else {
entry.autodrain();
}
});

Categories

Resources