How to pass String in to fs.readFileSync - javascript

I'm trying to convert string in to Buffer using readFileSync.It's return buffer with hard coded string.but not when i pas string.
----working ---
const buffer = fs.readFileSync('./test/JFwZCrdEojAr09ajT8EPZmo.jpg',{ encoding: 'utf8' });
----not working ---
var pathString = './test/JFwZCrdEojAr09ajT8EPZmo.jpg';
const buffer = fs.readFileSync(pathString,{ encoding: 'utf8' });
i'm getting bellow error
Error: ENOENT: no such file or directory, open
'./test/JFwZCrdEojAr09ajT8EPZmo.jpg'
Both ways working fine in local machine.but when deploy in to server,above happening.

Both should be work. check your image file still exists.

Related

React Native get real path of file on Android

I'm using react-native-document-picker to select a file and react-native-fs to upload the file.
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles],
copyToCacheDirectory: false
});
I'm getting the uri as - content://com.android.providers.media.documents/document/image%3A24
Then I'm converting this to actual path using react-native-get-real-path.
RNGRP.getRealPathFromURI(res[0].uri)
.then(filePath =>{
realFilePath = filePath
console.log("real-path-->"+filePath)
ToastAndroid.show(filePath, ToastAndroid.SHORT);
})
The above method gives the path as /storage/emulated/0/Download/output-onlinepngtools.png but this working for few files, for others I'm getting null as the real-path.
This is the error I see while uploading the file - [Error: Socket is closed]

Node.JS spawning Python to process binary image gives error 'node error spawn ENAMETOOLONG'

I'm trying to save an image by spawning a python process from a node.js script. The image is passed as a binary data file from a Node.JS script to a Python process.
The Script index.js spawns a python script my_py.py, then passes it a binary image data file. The python script my_py.py captures the binary image data and saves it to the directory assets/media.
The problem is the image isn't saved to the directory and I get the error error spawn ENAMETOOLONG.
Could you please help me spot the problem and to fix the code?
Thanks in advance!
index.js:
const spawn = require("child_process").spawn;
const fs = require('fs');
let params = {
"image":readDataset()
}
// Launch python app
const pythonProcess = spawn('py',['my_py.py', JSON.stringify(params)]);
// Print result
pythonProcess.stdout.on("data", (data) =>{
console.log(data.toString());
});
// Read errors
pythonProcess.stderr.on("data", (data) =>{
console.log(data.toString());
});
function readDataset() {
try {
return fs.readFileSync('color.png', 'binary');
}
catch (err) {
return err;
}
}
my_py.py:
import sys, json
params = json.loads(sys.argv[1]) # Load passed arguments
import numpy as np
import cv2
import os
fileName = "image.png" # file name
fileData = params['image'] # Capture file
# Convert Image to Numpy as array
img = np.array(fileData)
# Save file to local directory
cv2.imwrite(os.path.join('assets/media/', f'{fileName}'), img)
cv2.waitKey(0)
# Results must return valid JSON Object
print("File saved!")
sys.stdout.flush()
The error says it all: the command you are constructing is too long.
The thing you need to be aware of is that operating systems limits how long a command can be. For Linux this is around 4096 bytes though you can modify this value. For Windows this is 8191 bytes and for Mac OS this is around 250k bytes.
Part of the reason for this is because these OSes were written in C/C++ and in C/C++ code, not enforcing buffer size limit is an invitation to buffer overrun (the infamous stack overflow or underflow bug!!). Truly making input size unlimited result in slow code because you will not be using simple arrays for input buffer in that case but more complicated data structures.
Additionally, not having any limit on command length is a vector for DOS attacks. If you run an OS that does not have command size limit and I know for sure you have 32GB of RAM all I need to do to crash your system is construct a 32GB command!!
TLDR
The correct way to pass large data between processes is what you've been doing over the internet - upload/download the data! The simplest implementation is to just pass the data via the stdin of the python process you are connected to:
const spawn = require("child_process").spawn;
const fs = require('fs');
let params = {
"image":readDataset()
}
// Launch python app
const pythonProcess = spawn('py',['my_py.py']);
// Pass image data
pythonProcess.stdin.write(JSON.stringify(params) + '\n');
// Print result
pythonProcess.stdout.on("data", (data) =>{
console.log(data.toString());
});
// Read errors
pythonProcess.stderr.on("data", (data) =>{
console.log(data.toString());
});
function readDataset() {
try {
return fs.readFileSync('color.png', 'base64');
}
catch (err) {
return err;
}
}
In the code above I end the JSON "packet" with a newline so that the python code can read until end of line for a single packet. You can use any convention you like. For example I also often use the nul character (0x00) to mark end of packet and HTTP use two newlines ('\n\n') to mark end of header etc.
In any case I read the image file as base64 because binary data is invalid in JSON. In your python code you can do a base64 decode to get the image back. Additionally base64 does not include newlines ('\n') in its character set so converting the image to base64 ensure you don't get a newline inside your JSON data.
To get the image just read from stdin:
import sys, json, base64
params = json.loads(sys.stdin.readline())
import numpy as np
import cv2
import os
fileName = "image.png" # file name
fileData = base64.b64decode(params['image']) # Capture file
# Convert Image to Numpy as array
img = np.array(fileData)
# Save file to local directory
cv2.imwrite(os.path.join('assets/media/', f'{fileName}'), img)
cv2.waitKey(0)
# Results must return valid JSON Object
print("File saved!")
sys.stdout.flush()

React-native Invalid UTF-8 detected while trying to read a image file

I am trying to read an image file using the URI using react-native-fs and redux-saga:
file:///var/mobile/Containers/Data/Application/605FB6C0-869C-4128-883E-A59616933C64/Documents/images/52108C66-A087-4942-9DD4-22CBD0327089.jpg
Below is the line where I am getting an error while trying to read the image file:
const imageFile = yield call([RNFS, RNFS.readFile], logo.uri);
Below is the error I am getting:
Error: Invalid UTF-8 detected
at decodeSymbol (utf8.js:194)
at Object.utf8decode [as decode] (utf8.js:206)
at FS.common.js:150
at tryCallOne (core.js:37)
at core.js:123
at JSTimers.js:301
at _callTimer (JSTimers.js:154)
at _callImmediatesPass (JSTimers.js:202)
at Object.callImmediates (JSTimers.js:470)
at MessageQueue.__callImmediates (MessageQueue.js:275)
at MessageQueue.js:140
Can someone please tell me what I am doing wrong?
This is how it worked for me with a JPEG file on iOS :
(...)
var RNFS = require('react-native-fs');
(...)
var uri = '{your file uri}'
var img = 'file:///' + (uri.replace('file://', '')); // Must do that for RNFS
RNFS.readFile(img, 'base64') // 'base64' to process binary format
.then((file) => {
console.log("Getting image");
console.log(file);
})
RNFS only read file as string, the default encoding is utf8. image is binary file, you should try some other library to read it

Node.js - HTTPS PFX Error: Unable to load BIO

I'm trying to make a HTTPS request-promise. I already know that the PFX is good and that is not the issue (I have a similar sample app working).
I am doing the following:
var request = require('request-promise');
...
options.pfx = fs.readFileSync('myfile.pfx');
options.passphrase = 'passphrase';
I am passing my options into an request.
request.post(options);
I then try to build the request I get the following error:
_tls_common.js:130
c.context.loadPKCS12(pfx, passphrase);
^
Error: Unable to load BIO
at Error (native)
at Object.createSecureContext (_tls_common.js:130:17)
at Object.exports.connect (_tls_wrap.js:955:21)
at Agent.createConnection (https.js:73:22)
at Agent.createSocket (_http_agent.js:174:16)
at Agent.addRequest (_http_agent.js:143:23)
at new ClientRequest (_http_client.js:133:16)
at Object.exports.request (http.js:31:10)
at Object.exports.request (https.js:163:15)
at Request.start (/Users/filomeno/workspace/sla-crawler/node_modules/request/request.js:747:30)
at Request.write (/Users/filomeno/workspace/sla-crawler/node_modules/request/request.js:1369:10)
at end (/Users/filomeno/workspace/sla-crawler/node_modules/request/request.js:561:16)
at Immediate._onImmediate (/Users/filomeno/workspace/sla-crawler/node_modules/request/request.js:589:7)
at processImmediate [as _immediateCallback] (timers.js:374:17)
I have a sample app where the same code works.
I've tried to convert to .p12 without success.
Does anyone have an idea what this error might refer to?
Edit:
I'm using lodash to do a merge of 2 objects with dinamic properties and static properties
_.merge(options, _this.requestOptions);
And that was causing the problem
Looking at the nodejs source code (specifically this file https://github.com/nodejs/node/blob/master/src/node_crypto.cc)
the error is thrown by this function
// Takes .pfx or .p12 and password in string or buffer format
void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
...
In line 964
in = LoadBIO(env, args[0]);
if (in == nullptr) {
return env->ThrowError("Unable to load BIO");
}
Where the LoadBIO returns null
// Takes a string or buffer and loads it into a BIO.
// Caller responsible for BIO_free_all-ing the returned object.
static BIO* LoadBIO(Environment* env, Local<Value> v) {
HandleScope scope(env->isolate());
if (v->IsString()) {
const node::Utf8Value s(env->isolate(), v);
return NodeBIO::NewFixed(*s, s.length());
}
if (Buffer::HasInstance(v)) {
return NodeBIO::NewFixed(Buffer::Data(v), Buffer::Length(v));
}
return nullptr;
}
Perhaps the buffer is somehow not readable? Also it seems that the function is expecting an utf-8 encoded string.
Some ideas:
Are you sure the path to the file is correct?
Maybe encoding issue? Did you try to set fs.readFileSync() encoding explicitly?
Try with fs.readFile(<filename>, <encoding>, function(error, data){}) to see if it throws an error?

fswebcam: getting a dataURI via Node.js

I have fswebcam running on a Raspberry Pi. Using the command line, this saves JPG images.
I now want to receive these images in a Node.js application, and send them on to be used in a browser via dataURI.
On Node.js, I do:
var exec = require('child_process').exec;
exec("fswebcam -d /dev/video0 -r 160x120 --no-banner --save '-'", function(err, stdout, stderr) {
var imageBase64 = new Buffer(stdout).toString('base64');
I then send imageBase64 to the browser.
In the browser, setting the received data as the data URI fails:
image.src = "data:image/jpg;base64," + imageBase64;
Doing the above with a data URI created from a stored JPG created by fswebcam (via an online generator) works fine.
What am I not seeing here regarding formats and encodings?
The Content-Type should probably be image/jpeg and not image/jpg.
Also, the new Buffer(stdout) is redundant since stdout is already a Buffer, so you can just do stdout.toString('base64').
Lastly, if it's the data itself that is bad, you can double-check your base64-encoded output with this webpage or by writing stdout to disk and using the file command on it to ensure it's intact.
A little late but as I had same problem while playing with fswebcam from Node, the correct way would be to either use spawn and listen to "data" events on the spawned child's stdout stream. Or if you use exec then pass the encoding to be "buffer" or null as then the stdout argument to the callback will be again a Buffer instance, because otherwise by default it's utf-8 encoded string as stated in the exec docs
child_process.exec("fswebcam -", { encoding: "buffer" }, (error, stdout, stderr) => {
// stdout is Buffer now;
});

Categories

Resources