Module not found : Can't resolve 'fs' in Electron/Nextjs - next.js

I'm trying to check if a file exist and if not, starts to download in my eletron app.
The error i have is the next one :
error - ./node_modules/electron/index.js:1:0
Module not found:can't resolve 'fs'
null
Where i use the function
mainWindow.webContents.session.on(
'will-download',
.....
ipcMain.on('folder', (event, arg) => {
if (arg === 'check') {
const folder =
app.getPath('userData') +
'\\Local Storage\\' +
privateHash.split('.')[0];
var file = searchFile(folder);
if (file != null) {
OpenApp(
folder + '\\' + file,
meeting,
token,
company,
avatar,
scene
);
} else {
sending a message to the renderer to download the file
}
The searchFile function is something like this :
const searchFile = (folder) => {
var fs = require('fs');
var files = fs.readdirSync(folder.split('.')[0]);
....
I have looked in stackOverflow to similar problems and try their solutions, but for me it doesn't work.If somebody can help it will be great.
I put nodeIntegration, in package.json browser..fs:false,path:false,os:false..,i add to next.config.js webpack config , nothing is working for me

you are probably trying to run server side code on the browser, that is very common, i would suggest that you follow the calls stack and figure out where that code is being run a browser environment and and conditionally skip, EX
if (typeof window === 'undefined') {
// do server side stuff ex. you can run your function here.
} else {
// if you are in a client environment do nothing and return
return;
}

Related

Firebase Storage & Cloud Functions - ECONNRESET

I developed a Firebase Cloud function that processes several manipulations on uploaded images.
My code is based on this documentation article and this Cloud Function example. Hence, it is using Google Cloud Storage package.
It is working fine almost all the time, but sometimes I am getting this error when uploading to or deleting from Storage :
Error: read ECONNRESET
at exports._errnoException (util.js:1026:11)
at TLSWrap.onread (net.js:569:26)
I am using the default bucket of my application, referenced by event.data.bucket.
Let me know if you need additional information or code snippets, even if my code is really close to the Function example I linked before.
I found this GitHub issue, but I checked that I am returning a promise everytime. For example, here is the deletion part that triggers the error :
index.js
exports.exampleFunction = functions.storage.object().onChange(event => {
return f_thumbnails.exampleFunction(event);
});
example_function.js
module.exports = exports = function (_admin, _config) {
admin = _admin;
config = _config;
return {
"exampleFunction": function (event) {
return exampleFunction(event);
}
};
};
const exampleFunction = function (event) {
const gcsSourceFilePath = event.data.name;
const gcsSourceFilePathSplit = gcsSourceFilePath.split('/');
const gcsBaseFolder = gcsSourceFilePathSplit.length > 0 ? gcsSourceFilePathSplit[0] : '';
const gcsSourceFileName = gcsSourceFilePathSplit.pop();
const gceSourceFileDir = gcsSourceFilePathSplit.join('/') + (gcsSourceFilePathSplit.length > 0 ? '/' : '');
// Not an image
if (!event.data.contentType.startsWith('image/')) {
console.log('Not an image !');
return;
}
// Thumbnail
if (gcsSourceFileName.startsWith(config.IMAGES_THUMBNAIL_PREFIX)) {
console.log('Thumbnail !');
return;
}
const bucket = gcs.bucket(event.data.bucket);
const gcsThumbnailFilePath = gceSourceFileDir + config.IMAGES_THUMBNAIL_PREFIX + gcsSourceFileName;
// File deletion
if (event.data.resourceState === 'not_exists') {
console.log('Thumbnail deletion : ' + gcsThumbnailFilePath);
return bucket.file(gcsThumbnailFilePath).delete().then(() => {
console.log('Deleted thumbnail ' + gcsThumbnailFilePath);
});
}
...
This seems to be related to the google-cloud-node library's handling of sockets, and the default socket timeout in the Cloud Functions environment.
One solution verified by a user is to modify the way the library invokes requests, to not keep the socket open forever by specifying forever: false, eg.
var request = require('request').defaults({
timeout: 60000,
gzip: true,
forever: false,
pool: {
maxSockets: Infinity
}
});
This is hardcoded in packages/common/src/utils.js, so you'll need to vendor a copy of the modified library into your project rather than include it as an NPM dependency. See the related public issue for more details on the issue and a link to a fork with the patch applied.

Where are uploaded file in a deployed Meteor app?

I'm a bit confused about where meteor saves static files (the ones in the /public folder);
I have a method for uploading files:
saveFile: function(blob, name, path, encoding) {
if (!Meteor.isServer) return;
var fs = Npm.require('fs'),
chroot = Meteor.chroot || 'public';
//path = cleanPath(path);
name = cleanName(name || 'file');
encoding = encoding || 'binary';
path = chroot + (path ? '/' + path + '/' : '/');
var basePath = process.env.PWD;
var fullPath = basePath + '/' + path + name;
var dirs = (path.split('/'));
var currentCreatedPath = basePath;
//create needed folders
dirs.forEach(function(dir, index) {
if (dir.length > 0) {
currentCreatedPath = currentCreatedPath + '/' + dir;
if (!fs.existsSync(currentCreatedPath)){
fs.mkdirSync(currentCreatedPath);
}
}
});
fs.writeFile(fullPath, blob, encoding, function(err) {
if (err) console.log(err); //throw (new Meteor.Error(500, 'Failed to save file.', err));
else console.log('The file ' + fullPath + 'has been saved');
});
function cleanPath(str) {
if (str) return str.replace(/\.\./g,'').replace(/\/+/g,'').replace(/^\/+/,'').replace(/\/+$/,'');
}
function cleanName(str) {
return str.replace(/\.\./g,'').replace(/\//g,'');
}
return true;
}
Then in the template I reach the file like this:
{{#each this.files}}
<li>
<a href="/{{path}}" target="_blank">
{{title}}
</a>
</li>
{{/each}}
where path is /public/folder/to/file/file.ext
This works great locally; but once deployed, it is not able to find uploaded files;
in which folder of the deployed project does meteor save the files?
Its not advised to use this practice. If you deploy your app and have more than one instance or 'drone' running each one will not be able to see each others files.
Its best to use something like s3 to store your files on a 3rd party server due to this.
Anyway If you do decide to store your files on the same machine you just need to use an absolute path outside your meteor project.
If you use the public folder Meteor will restart due to the file change. If you use the bundled asset static folder you will have a bit of trouble finding your files.
Something like this may help (saves on your desktop):
var path = Npm.require("path").resolve("~/Desktop/");
saveFile(blob, name, path, encoding)
To view the files you can have some kind of proxy (if you use iron router):
Server side code (may need some tweaking):
Router.route('/file/:filename', function() {
var self = this;
var res = this.response;
var filename = this.params.filename
var path = Npm.require("path");
var fs = Npm.require("fs");
fs.readFile(path.join(path.resolve("~/Desktop"), filename), function(err, fileContent) {
if(err) console.log(err);
self.response.statusCode = 200;
//self.response.setHeader("Content-Type", response.headers['content-type']);
self.response.setHeader("Content-disposition", filename);
self.response.end(fileContent);
});
}, { where: 'server' });
For simplicity, I've used your Desktop folder (OS X). I'd advise to use another more secure folder.
Then you can use the url http://localhost:3000/file/your_file_name to download it.

How to specify the location of kml file when using geoxml3 parser with meteor js

I have been trying to parse a kml file using the geoxml3 parser. The geoxml3.js file is put in the public folder. The parser is working fine if I put the kml file inside the public folder.
geoXml.parse('doc.kml'); // this is working fine
But how can I make it work if the kml file is located somewhere else, say in the 'uploads' folder outside the public folder. I have tried,
geoXml.parse(uploadPath+'/doc.kml');
but this is not working. How should I specify the file path ? I can't put the kml files in the public folder as any change inside the folder will make the page refresh.
Please help me out.
Haven't tried this one, but Assets.getText() may be what you're looking for. The documentation
specifies that you pass it a file path relative to your private directory.
Well, could not resolve the path issue. Assets.getText() is dependent on the private folder and also it doesn't stop the server from restart. But found an alternative solution, where you can upload the file to any folder within your project app and read from it.
// On client side
Meteor.call('getKmlString', kml_file_name, function(error, kml_string) {
if (error) {
console.log('ERROR in getting kml string');
console.log(error);
} else {
console.log('GOT Kml String');
geoXml.parseKmlString(kml_string);
}
});
// On server side
Meteor.startup(function() {
// code to run on server at startup
return Meteor.methods({
getKmlString: function(kml_file_name) {
var content = '';
var fs = Npm.require('fs');
var encoding = encoding || 'binary';
var chroot = Meteor.chroot || 'uploads';
var path = chroot + (path ? '/' + path + '/' : '/');
var content = fs.readFileSync('../../../../../' + path + kml_file_name, "utf-8", function read(err, data) {
if (err) {
throw err;
}
});
return content;
},
});
});

[meteor][0.6.*] With meteorjs, how to download file with Meteor.http?

In my meteor app, the server try to download some file to store them on filesystem.
I use Meteor.http package to do that, but in fact, if file are downloaded, they seems to be corrupted.
var fileUrl = 'http://cdn.sstatic.net/stackoverflow/img/sprites.png?v=5'; //for example
Meteor.http.call("GET", fileUrl, function funcStoreFile(error, result) {
"use strict";
if (!error) {
var fstream = Npm.require('fs'),
filename = './.meteor/public/storage/' + collectionId;
fstream.writeFile(filename, result.content, function funcStoreFileWriteFS(err) {
if (!err) {
var Fiber = Npm.require('fibers');
Fiber(function funcStoreImageSaveDb() {
MyfileCollection.update({_id: collectionId}, {$set: {fileFsPath: filename}});
}).run();
} else {
console.log('error during writing file', err);
}
});
} else {
console.log('dl file FAIL');
}
});
I did a symlink from public/storage to ../.meteor/public/storage to enable direct download from url (http://localhost:3000/storage/myfileId)
When i compare the file downloaded with this system and the same file downloaded directly from a browser, they are different. What's wrong with my conception?
I had a similar problem and made a solution based on this discussion:
on https://github.com/meteor/meteor/issues/905
By using the request library, which meteor is using under the hood as well, one can avoid the problem with binary downloads. Besides I would recommend not saving small files to the filesystem but base64 encoded in mongodb directly. This is the easiest solution, if you plan to deploy to meteor.com or other cloud services.
An other glitch I found when saving files to the public dir in development is that meteor is reloading the files for every change in the public dir. this can lead to data corruption as chunks of the file are being downloaded. Here some code i am using based on the above discussion.
Future = Npm.require("fibers/future")
request = Npm.require 'request'
Meteor.methods
downloadImage: (url) ->
if url
fut = new Future()
options =
url: url
encoding: null
# Get raw image binaries
request.get options, (error, result, body) ->
if error then return console.error error
base64prefix = "data:" + result.headers["content-type"] + ";base64,"
image = base64prefix + body.toString("base64")
fut.ret image
# pause until binaries are fully loaded
return fut.wait()
else false
Meteor.call 'downloadImage', url, (err, res) ->
if res
Movies.update({_id: id}, {$set: {image: res}})
Hope this is helpful.

dynamically add files to the public folder and getting the refreshed results in meteor

I'm playing around with the idea of using Meteor as a backend for creating a static html generator (with an admin UI).
I want that, when triggered, a new file will be created on the public folder and instantly reviewed by the author on an iframe embed in the html.
The file gets created but two side effects happen:
The server is restarted.
The file is cached - so the user can't see that the change took place.
Any ideas?
if (Meteor.is_client) {
Template.hello.events = {
'click input' : function () {
Meteor.call('makeFile', 'filename.html', function(error, result){
alert(result);
});
//window.location = '/filename.txt';
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
};
}
if (Meteor.is_server) {
var fs = __meteor_bootstrap__.require('fs');
Meteor.startup(function () {
// code to run on server at startup
});
Meteor.methods({
'makeFile': function(fileName) {
/*
fs.unlink("public/"+fileName, function (err) {
if (err) throw err;
console.log('successfully deleted ');
});
*/
fs.writeFile("public/"+fileName, "<html><body><h1>test</h1></body></html>", function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved! "+ fileName);
}
});
return fileName;
}
});
}
I think the meteor server restarts whenever you change any file in a meteor subdirectory. So to prevent this don't write your files within the meteor app directory, make a created_files directory one level up or something. This is a good idea anyway, to separate the generated files from the code that's generating them.
Easiest way to show the content in the admin interface is probably to write it to the database (as opposed to trying to watch for directory changes). No sense re-inventing the wheel, since Meteor is designed to watch for db updates.
Create a collection (at the top, so it's on client & server):
GeneratedFiles = new Meteor.Collection("generated_files");
Then assign the file contents to a variable before writing them and in your fs.writeFile callback:
if(err) {
console.log(err);
} else {
GeneratedFiles.insert({name: fileName, contents: fileContents});
console.log("The file was saved! "+ fileName);
}
And then auto-publish the file contents to template in the client code (not sure why you want to use an iframe, seems like a div would work fine. But either way would probably work).
Hope that helps. And good luck, I think meteor is a great framework for this kind of thing. Most of the admin interfaces I use are still entirely synchronous and just annoying to work with.

Resources