Use node.js to save json file - javascript

I am very new to Node server/javacsript. So I am sorry if this might be stupid
question/topic.
I intended to create a very simple solution to open JSON file, load to list, and save it back to my local disk (running node.js server).
Could you please help me out, what I am doing wrong? I am running app in browser using react.
index.js containing
var fs = require('fs');
var fileName = './test.json';
var file = require('./test.json');
alert(file.name + " " + file.age);
file.name = "Peter";
alert(file.name + " " + file.age);
fs.writeFile('./test.json', JSON.stringify(file), function (err) {
if (err) return alert(err);
console.log(JSON.stringify(file));
alert('writing to ' + fileName);
});
Before I was not even able to open JSON file. I needed to include this property into the webpack config file.
node: {
fs: 'empty'
}
Now I am able to open JSON file, change it virtually, but unable to save it.
In chrome developer tools, it prints "fs.writeFile is not a function" into console.
Thank you very much.

When you included the property in your webpack config
node: {
fs: 'empty'
}
You told webpack that the module fs should just be an empty object. You can confirm this by simply putting a console.log(fs) in your file to see it is indeed empty.
Beyond that, fs is not going to work in your browser. fs expects the node.js runtime (which includes non-JavaScript things in order to make it work), not your browser's runtime.
If you want a user to save a file, you'll have to use a browser based saving solution. You won't be able to just arbitrarily write files like that outside of something like your browser's local storage.

Related

Save data to an external file

Hello, I am currently developing a website for my personal needs for which I need to be able to regularly save data in a "data.json" file, which I can then retrieve for later use.
I then remembered that I had already used the "file sync" module of NodeJs before, but this time I can't manage to use it with my project as it doesn't seem to apply to my html files...
I suspect that there are other easier solutions or that I must be using NodeJs wrong in this case.
I use the sublime text editor and I work on 2 html files linked to the same script.js and style.css file
Would you have solutions to propose to me?
Thank you, cordially,
Florent
Let's say at the backend.
const htmlTxt = `
<html>
...
</html>
`
// write the file locally
fs.writeFileSync("sampleHtml.html", htmlTxt);
// read the contents of the file
console.log(fs.readFileSync("sampleHtml.html", "utf8"));
I would use the File system module.
So on your nodeJS server, you would have to add:
const fs = require('fs');
then create your json:
let jsonElement = {
aa: 'aa',
test: 123,
};
let data = JSON.stringify(jsonElement);
And save it to file
fs.writeFileSync('json_file.json', data);
https://nodejs.org/api/fs.html

Ionic 3 Prod Build With Version Number

I use the following command when building an ionic project for desktop
ionic cordova build browser --prod
Which results in the following file being generated
build/main.js
However I would like to be able to add a version number to the generated file automatically as part of the build process. So would end up with something like
build/main.js?version=1.00
as to avoid needing to clear the browser cache after every prod build.
Is there a flag for this, or is it something I must do manually?
Any advice would be great!
EDIT:
My solution is on GitHub for anyone interested!
https://github.com/RichardM99/ionic-3-version-build-file-hook
Here's some advice - You can create a cordova hook.
Hooks are scripts that you want to be executed at different stages of the build process. In your case, you are looking at a script which renames the main.js file after the build event is finished, or in other words a 'after_build' type hook.
The script will usually be a Node.js file, although you can have other types of scripts executed as well.
One more thing. Since you want to get around cache, you wont be renaming the file itself. What you will want to do is rather replace the reference to "main.js" in you "index.html" to include a random or maybe your actual version number.
I have pointed you in a direction, but won't spoonfeed. Look up documentation on cordova hooks. They are super simple if you understand Javascript/Node
Something like this should get the job done:
var index_orig = fs.readFileSync(path-to-index.html, 'utf8');
var index_new = index_orig.replace("main.js", "main.js?version="+version_num);
fs.writeFileSync(path-to-index.html, index_new, 'utf8');
If you want the actual build number, you can read your config.xml and parse it to get it's value.
Hope it helps.
I wrote blog long time ago
In my build pipeline i have command to set version
version "$(app.versionPrefix)$(Build.BuildNumber)"
$(app.versionPrefix) - is a prefix version such as 0.1.
$(Build.BuildNumber) - is build version
Then I have environment file
export const environment = {
apiUrl: 'https://....',
production: true,
version: '0.0.57'
}
Then i have js script to update version in environment and config.xml
var replace = require('replace-in-file');
var package = require("./package.json");
var buildVersion = package.version;
const options = {
files: ['config.xml'],
from: /" version="([0-9]*.[0-9]*.[0-9]*)"/g,
to: "\" version=\""+ buildVersion + "\"",
allowEmptyPaths: false,
};
const optionsEnv = {
files: ['src/environments/environment.prod.ts'],
from: /version: '(.*)'/g,
to: "version: '"+ buildVersion + "' ",
allowEmptyPaths: false,
};
try {
let changedFiles = replace.sync(options);
if (changedFiles == 0) {
throw "Please make sure that file '" + options.files + "' has \"version: ''\"";
}
changedFiles = replace.sync(optionsEnv);
if (changedFiles == 0) {
throw "Please make sure that file '" + optionsEnv.files + "' has \"version: ''\"";
}
console.log('Build version set: "' + options.to + '"');
}
catch (error) {
console.error('Error occurred:', error);
throw error
}
NOTE: you need to install plugin replace-in-file
Then in build pipe line I am running this script
node ./replace.build.js
In your case if you need only for browser you can tune script.

Finding a Relative File Path to Parse an Excel File

I'm building a web app using Node.JS that at the very least should allow users to to upload excel spreadsheets (.xlsx) and then using an excel parser (currently using node-xlsx - https://www.npmjs.org/package/node-xlsx), I want to be able to find this file, parse it, and print its contents to the console. So far, I have the file uploaded and stored, but am having trouble specifying the file path my app should search down.
I believe my troubles are that I am trying to do this on the server-side, and I am telling my app to search through a users directory for this file when it does not have access.
Here is example code:
var fullfile;
app.post('/upload', function (request, response) {
var fstream;
request.pipe(request.busboy);
request.busboy.on('file', function (fieldname, file, filename) {
console.log('Uploading: ' + filename);
fstream = fs.createWriteStream('./storedFiles/' + filename);
file.pipe(fstream);
fstream.on('close', function () {
response.redirect('success');
console.log('Uploaded to ' + fstream.path);
fullfile=fstream.name;
var obj = xlsx.parse(__dirname + fullfile);
console.log(obj);
});
});
});
This produces the error:
return binding.open(pathmodule._makelong(path) stringtoflags(flags) mode)
error: ENOENT, no such file or directory 'C\Users(file path on my local machine here)
Can anyone point out a way of doing this that I am missing? it has to do with fs methods I feel.
Thank you
First of all, don't use the filename that user provided when saving the file - you will get duplicates and it could be a security risk (in general, never trust user provided data). Just use your own value instead - it is more standard to use your own naming convention to prevent duplicates or to use a tmp file provided by the OS.
To solve your issue, try:
Requiring path at the top of your file:
var path = require('path');
and changing the value of fullfile to:
fullfile = path.join(__dirname,fstream.path)
then pass fullfile to xlsx.parse:
var obj = xlsx.parse(fullfile);

How to fetch file content (basically read) a local file in javascript for UIAutomation iOS

Is there a possible way to read a local file in JavaScript.
MyFolder:
db.csv
Parse.js
Trying to fetch the contents of file db.csv in Parse.js, But in vain.
Can you share some links where I can get enough knowledge how to read a file.
Running Instruments in Xcode5, with test scripts in .js file where I have to feed in some values from a .csv file.
iOS UIAutomation, apple provides an api for running a task on the target's host.
performTaskWithPathArgumentsTimeout
Using this, we can have a bash script to printout the contents of a file that we wanted to fetch in the first case.
Bash script can be as simple as this for this requirement.
#! /bin/bash
FILE_NAME="$1"
cat $FILE_NAME
Save it as for example FileReader.sh file.
And in your automation script,
var target = UIATarget.localTarget();
var host = target.host();
var result = host.performTaskWithPathArgumentsTimeout(executablePath,[filePath,fileName], 15);
UIALogger.logDebug("exitCode: " + result.exitCode);
UIALogger.logDebug("stdout: " + result.stdout);
UIALogger.logDebug("stderr: " + result.stderr);
where in,
executablePath is where the command need to be executed.
var executablePath = "/bin/sh";
filePath is the location of the created FileReader.sh file. When executed, outputs the content to standard output (in our requirement).
[give full absolute path of the file]
fileName is the actual file to fetch contents from.
[give full absolute path of the file] In my case I had a Contents.csv file, which I had to read.
and the last parameter is the timeout in seconds.
Hope this helps others, trying to fetch contents (reading files) for performing iOS UIAutomation.
References:
https://stackoverflow.com/a/19016573/344798
https://developer.apple.com/library/iOS/documentation/UIAutomation/Reference/UIAHostClassReference/UIAHost/UIAHost.html
If the file is on the same domain as the site you're in, you'd load it with Ajax. If you're using Ajax, it's be something like
$.get('db.csv', function(csvContent){
//process here
});
Just note that the path to the csv file will be relative to the web page you're in, not the JavaScript file.
If you're not using jQuery, you'd have to manually work with an XmlHttpRequest object to do your Ajax call.
And though your question doesn't (seem to) deal with it, if the file is located on a different domain, then you'd have to use either jsonP or CORS.
And, just in case this is your goal, no, you can't, in client side JavaScript open up some sort of Stream and read in a file. That would be a monstrous security vulnerability.
This is a fairly simple function in Illuminator's host functions library:
function readFromFile(path) {
var result = target.host().performTaskWithPathArgumentsTimeout("/bin/cat", [path], 10);
// be verbose if something didn't go well
if (0 != result.exitCode) {
throw new Error("readFromFile failed: " + result.stderr);
}
return result.stdout;
}
If you are using Illuminator, this is host().readFromFile(path).

On Node.JS, Jade Templates, and Javascript Options Objects

I am currently building a project with node.js in Windows. I am using a batch file to assemble resources and build jade templates via the command line. With Jade, I am using the switch -o to defines a JS object that fills localized content in the template
For awhile, everything worked nicely. However, changes to my JSON lookup have resulted in an error:
"The input line is too long"
Researching the error, I found that windows shell has a limit on how long your lines can be. Unfortunately, I need the whole lookup object for my project. However, I started wondering if jade can accept a path to my lookup file instead of a string with the contents of the file. Currently, I'm building the contents into a variable and calling jade with that ala:
SetLocal EnableDelayedExpansion
set content=
for /F "delims=" %%i in (%sourcedir%\assets\english.json) do set content=!content! %%i
::use the json file as a key for assembling the jade templates
call jade %sourcedir% --out %destdir% -o"%content%"
EndLocal
If I could use a path to the lookup file, it would be much easier. However, I am usure how to do that (if it's even possible). and Jade's documentation is a bit lacking.
So, in short, is it possible for Jade to accept a filepath to a JS object rather than a string containing the object? Is there a better way to contruct the jade call that wont push it past the limit?
Write a node.js script that will read your "assets" and will call a jade. Something like:
var fs = require('fs'),
_ = require('underscore'),
async = require('async');
var sourceDir = 'path to the directory with your jade templates',
destinationDir = 'path to the directory where you want the result html files to be contained in';
async.waterfall([
async.parallel.bind(null, {
serializedData: fs.readFile.bind(null, 'assets/english.json'),
files: fs.readDir.bind(null, sourceDir),
}),
function (result, callback) {
var data = JSON.parse(result.serializedData),
files = result.files;
async.parallel(_.map(files, function (file) {
return async.waterfall.bind(null, [
fs.readFile.bind(null, sourceDir + file),
function (jadeSource, callback) {
process.nextTick(callback.bind(null, jade.compile(jadeSource)(data)));
},
fs.writeFile.bind(null, destinationDir + file)
]);
}), callback);
}
], function (err) {
if (err) {
console.log("An error occured: " + err);
} else {
console.log("Done!");
}
});
Then in your batch file call this script directly, instead of enumerating the directory and calling the jade manually.
It will not only solve your problem, but also work much faster because:
I/O operations are done in parallel;
Node.js is only started once during the build process, as opposed to starting it for every single file as you do now.

Categories

Resources