I've been working with Node.js for a project and everything has been going well until now. I'm using express as well with node. Overall my goal is extremely simple...upload an image to the server in an uploads folder. The odd thing is the upload itself actually works but when I go to use the "rename" function it says the path is wrong/permissions with this error: ENOENT.
I've also tested to make sure that the path is 100% correct when being used by calling the read function to check for the file path. Seems to only break when it tries to modify the file so I've deduced it's a permissions issue (unless there's some sort of special requirement for the rename function). I noticed that every time a file gets uploaded the permissions set to "custom" and only give read permissions to every user except my username. I'll post the code that's related to this problem below:
/app/routes.js
var fs = require('fs');
app.post('/api/file-upload/:page_id', function(req, res) {
// fs.readFile(tmp_path, function (err, data) {
// if (err) throw err;
// console.log(data);
// });
var target_path = './public/images/' + req.files.featuredimg.name;
fs.rename(req.files.featuredimg.path, target_path, function(err) {
if (err) throw err;
fs.unlink(tmp_path, function() {
if (err) throw err;
res.send('File uploaded to: ' + target_path + ' - ' + req.files.featuredimg.size + ' bytes');
});
});
});
server.js
app.use(express.bodyParser({uploadDir:'./uploads'}));
Everything ends up in the root folder next to server.js in /uploads which works as intended. I just can't seem to modify them. I've tried everything I can think of and have looked up the problem. Hopefully it's a simple fix.
Hopefully someone out there can help me out with this problem. I'd really appreciate it!
Make sure you have created images folder under public. I had similar issue.
Related
I have followed a tutorial to produce a Twitter bot using node.js, github and Heroku. Everything works great, the bot pulls a random image from a folder at timed intervals and tweets the image.
I'm trying to change the process so that instead of pulling images from a local folder (called 'images'), it pulls them from a web hosted folder. For example, rather than get the images from the local /images folder, I'd like it to pull the image from http://mysite/images. I have tried changing what I think are the relevant bits of code below, but am having no luck. Could anybody offer some advice please?
The whole code is below, but for reference, the bits I have tried changing are:
var image_path = path.join(__dirname, '/images/' +
random_from_array(images))
and
fs.readdir(__dirname + '/images', function(err, files) {
In both cases above I tried changing the /images folder to http://mysite/images but it doesn't work. I get an error stating that no such folder can be found. I have tried changing/deleting the __dirname part too but to no avail.
Any help appreciated!
Full code below:
const http = require('http');
const port=process.env.PORT || 3000
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
res.end('<h1>Hello World</h1>');
});
server.listen(port,() => {
console.log(`Server running at port `+port);
});
var Twit = require('twit')
var fs = require('fs'),
path = require('path'),
Twit = require('twit'),
config = require(path.join(__dirname, 'config.js'));
var T = new Twit(config);
function random_from_array(images){
return images[Math.floor(Math.random() * images.length)];
}
function upload_random_image(images){
console.log('Opening an image...');
var image_path = path.join(__dirname, '/images/' +
random_from_array(images)),
b64content = fs.readFileSync(image_path, { encoding: 'base64' });
console.log('Uploading an image...');
T.post('media/upload', { media_data: b64content }, function (err, data,
response) {
if (err){
console.log('ERROR:');
console.log(err);
}
else{
console.log('Image uploaded!');
console.log('Now tweeting it...');
T.post('statuses/update', {
/* You can include text with your image as well. */
// status: 'New picture!',
/* Or you can pick random text from an array. */
status: random_from_array([
'New picture!',
'Check this out!'
]),
media_ids: new Array(data.media_id_string)
},
function(err, data, response) {
if (err){
console.log('ERROR:');
console.log(err);
}
else{
console.log('Posted an image!');
}
}
);
}
});
}
fs.readdir(__dirname + '/images', function(err, files) {
if (err){
console.log(err);
}
else{
var images = [];
files.forEach(function(f) {
images.push(f);
});
/*
You have two options here. Either you will keep your bot running, and
upload images using setInterval (see below; 10000 means '10 milliseconds',
or 10 seconds), --
*/
setInterval(function(){
upload_random_image(images);
}, 30000);
/*
Or you could use cron (code.tutsplus.com/tutorials/scheduling-tasks-
with-cron-jobs--net-8800), in which case you just need:
*/
// upload_random_image(images);
}
});
Well, my first answer to a question about building a twitter bot would probably be: "Don't do that!" (Because the world doesn't need more twitter bots.) But, putting that aside...
Your code is using the "fs" library, which is exactly what you needed for grabbing stuff from the local file system. That was fine. But now you want to grab stuff from web servers, which "fs" is not going to be able to do. Instead, you need a library that gives you the ability to make an HTTP or HTTPS request across the web and bring you back some data. There are different libraries that do this. Looks like you are already bringing in the "http" library, so I think you are on the right track there, but you seem to be using it to set up a server, and I don't think that's what you want. Rather, you need to use http as a client, and replace your fs.readFileSync() calls with the appropriate calls from the http library (if that's the one you choose to use) to pull in the data you want from whatever server has the data.
Hope that helps. And I hope your twitter bot is going to be a good little bot, not an evil one!
** Edit, I believe this is an issue with the initial boilerplate I started with (one using parcel) and is missing some part causing this issue. This seems to work just fine with electron-quick-start boilerplate **
I have searched around and can't find a solution. There is a youtube video tutorial showing how to read from the file system: https://www.youtube.com/watch?time_continue=292&v=PQZEymiWFh8
But I implement the same but get this error fs.readFile is not a function. I am doing this in a react electron app however. Here is how I am setting this up:
const fs = require('fs');
const { dialog } = window.require('electron').remote;
...
getFile() {
dialog.showOpenDialog((fileNames) => {
// fileNames is an array that contains all the selected
if(fileNames === undefined){
console.log("No file selected");
return;
}
fs.readFile(fileNames[0], 'utf-8', (err, data) => {
if(err){
alert("An error ocurred reading the file :" + err.message);
return;
}
// Change how to handle the file content
console.log("The file content is : " + data);
});
});
}
It gets the file name, but fs.readFile is throwing the not a function error. Anyone know a solution to this as it works in that tutorial video?
If i have the code below how can i edit the specific file and make the right corrections?
var p4 = require('C:/Program Files/nodejs/node_modules/p4');
var File = process.argv[2];
p4.edit(File, function(err, data) {
if (err) {
console.error(err.message);
}
console.log(data);
});
Your code looks correct to open the file for edit. If that returns any errors when you run it, you should post those here, but I'll assume that it returns a success message ("(file) opened for edit").
Opening the file for edit means that it is made writable on the local filesystem (i.e. the one where this code is running -- the file is the one you passed as an argument to the edit command). To actually modify the file you can use any other function at your disposal.
I am trying to save a project and its file using GridFS. I want to save project first and use "_id" of project as metadata for file.
Here is my code:
newProject.save(function (err,project) {
if (err) {
console.log('save error', err);
}
console.log("project added");
var id=poject._id;
var filepath = req.files.file.path;
var filename = req.files.file.name;
var writestream = gfs.createWriteStream({ filename: filename, metadata:id });
console.log(filepath);
fs.createReadStream(filepath)
.on('end', function() {
})
.on('error', function(err) {
console.log("error encountered"+err);//ENOENT,open error
})
.pipe(writestream);
});
I am getting following error:-
ENOENT, open '/tmp/45e85388793de'
I know that this error comes when the directory does not exists. As you can see I am writing the file after saving the project since I need to link the file to the project. That's why I have written the code to save the file inside callback function of project.save() but it is not working there. If I put the same code outside the .save block the same code works perfectly for same path. (I have displayed the path both inside and outside and they are same)
Finally I was able to fix this myself:-
File is saved in a temporary location. When you are inside the callback function your file is removed from that location and you are getting "No such file" error. Path and other variables still exists as part of js and that's why you are able to print them in console.
Solution: Above(Outside) callback function move your file to some other permanent location using:
fs.rename(req.files.file.path, "./someKnownPath/filename");
Keep note of that location. In your callback function use the new location as path and try saving the file in gridfs. Once the file is saved you may delete it file from that location(/someKnownPath/filename).
I succeed uploading file using node.js and the formidable module yet,
the file that got save on the disk is in some kind of a bad format ( bad encoding)
e.g. if I upload an image I can't view it, if I upload a txt file gedit provide the following msg:
"gedit has not been able to detect the character encoding.
Please check that you are not trying to open a binary file.
Select a character encoding from the menu and try again."
here is the code:
form.encoding = 'utf-8';
form.parse(req, function(err, fields, files) {
fs.writeFile('test.js', files.upload,'utf8', function (err) {
if (err) throw err;
console.log('It\'s saved!');
});
});
The problem is the that files.upload is not the content of the file, it is an instance of the File class from node-formidable.
Look at:
https://github.com/felixge/node-formidable/blob/master/lib/file.js
Instead of trying to write the file to disk again, you can just access the path to uploaded file like this and use fs.rename() to move it where you want:
fs.rename(files.upload.path, 'yournewfilename', function (err) { throw err; });
Is the form set to enctype="multipart/form-data"?
I've only used formidable with Express - the Express example works fine:
https://github.com/visionmedia/express/tree/master/examples/multipart