Nodejs&Formidable, Uploading images - javascript

if (sess.username) {
var form = new formidable.IncomingForm();
form.multiples = true;
form.uploadDir = __dirname + "/data";
form.parse(req, function (err, fields, files) {
if (fields.title.length < 120 || fields.content.length < 1000000) {
var articleData = new articleModel({
title: fields.title,
content: fields.content,
created_at: Date.now()
});
articleData.save(function (err) {
console.log('saved');
});
form.on('error', function (err) {
console.log('An error has occured: \n' + err);
});
}
else {
res.render('failed', {
message: 'Too much characters.'
});
}
});
res.redirect('/admin');
}
I was trying with this code but i got error like this:
Error: ENOENT: no such file or directory, open
'C:\Users\Użytkownik\Documents\GitHub\CFBlog\controllers\admin\data\upload_c2aff6d1c5930dd655caa436890aaf03'
at Error (native)

Seems like you don't have data/ folder in your __dirname.
Formidable just can't create file in folder that doesn't exist.

Related

fs.mkdir not creating directory nor giving error

The following code does not create a new directory, nor does it output any err
const fs = require("fs-extra");
fs.mkdir(dirPath, { recursive: true }, (err) => {
if (err) {
console.log("ERR: When attempting to mkdir", err);
} else {
console.log("MKDIR made " + dirPath);
}
cb(null, dirPath);
});
I would expect the directory to be created... or an error.
When I console.log(err) I find that the value of err is null.
How can I ensure this directory has been created?

What am I supposed to pass to cloudinary from formidable, I tried the image path/name that didnt work

I have the following parse of a stream in Next JS that is getting the file input for an image, it looks like it stores the image for me to pass to cloudinary but cloudinary says the image doesnt exist.
const form = new formidable.IncomingForm();
form.uploadDir = "./upload";
form.keepExtensions = true;
form.parse(req, (err, fields, files) => {
console.log(JSON.stringify(files));
const path = files.image.path + "/" + files.image.name
cloudinary.uploader.upload(path, function (error, result) {
console.log(result, error);
});
});
Here's the image path and name from the parse
{"image":{"size":35168,"path":"./upload/1547db49054ff2a2acb915a03","name":"test.png","type":"image/png","mtime":"2021-03-12T03:46:20.002Z"}}
and heres the error from cloudinary
[Error: ENOENT: no such file or directory, open './upload/7e1c5b9e3235ae38d12097300/test.png'] {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: './upload/7e1c5b9e3235ae38d12097300/test.png'
}
I must be missin something fundamental here.
UPDATE: I have tried writing to with fs, but still having no luck. dont quite get it. Is the image ever saved for so I can pass it to cloudinary.
const form = new formidable.IncomingForm();
form.uploadDir = "./";
form.keepExtensions = true;
form.parse(req, (err, fields, files) => {
console.log(JSON.stringify(files));
console.log(files.image.path);
var oldPath = files.image.path;
var newPath = path.join(__dirname, "upload") + "/" + files.image.name;
var rawData = fs.readFileSync(oldPath);
fs.writeFile(newPath, rawData, function (err) {
console.log(newPath);
const path = newPath;
cloudinary.uploader.upload(path, function (error, result) {
console.log(result, error);
});
});
});
For anyone else who has this problem you can pass the buffer which is the rawData variable and works like so
const form = new formidable.IncomingForm();
form.uploadDir = "./";
form.keepExtensions = true;
form.parse(req, (err, fields, files) => {
console.log(JSON.stringify(files));
console.log(files.image.path);
var oldPath = files.image.path;
var rawData = fs.readFileSync(oldPath);
console.log(rawData);
let cld_upload_stream = cloudinary.uploader.upload_stream(
{
folder: "sick-fits"
},
function(error, result) {
console.log(error, result);
}
);
streamifier.createReadStream(rawData).pipe(cld_upload_stream);

TypeError cannot read property 'length' of undefined in node js

my code app.js
it is to upload some of imges
I am getting the "TypeError: Cannot read property 'length' of undefined?
app.post('/upload', urlencodedParser, function(req, res) {
if (req.url == '/upload') {
var form = new formidable.IncomingForm();
form.uploadDir = "C:/Users/Abdulrahman Afify/myapp/";
form.keepExtensions = true;
form.multiples = true;
form.parse(req, function(err, fields, files) {
if (err) {
res.json({
results: "faild",
data: {},
message: 'Cannot upload Files Error is: ${err}'
});
}
var arrayOffiles = files[""];
if (arrayOffiles.length > 0) {
var fileNames = [];
arrayOffiles.forEach((eachFile) => {
fileNames.push(eachFile.path);
});
res.json({
result: "OK",
Date: fileNames,
numberOfImages: fileNames.length,
message: "upload images Successfully"
});
} else {
res.json({
result: "failed",
Date: [],
numberOfImages: 0,
message: "upload images failed"
});
}
});
} else {
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.write('<form action="fileupload" method="post" enctype="multipart/form-data">');
res.write('<input type="file" name="filetoupload" multiple ><br>');
res.write('<input type="submit">');
res.write('</form>');
return res.end();
}
});
ERROR: { if(arrayOffiles.length > 0){
TypeError: Cannot read property 'length' of undefined}
how can i solve it please in node.js
Use this
var arrayOffiles= files || [];
Instead
var arrayOffiles= files[""];

Node File System Create Directory and files on post route

I have a dashboard that generates JSON data and saves it as a .json file. This was initially written in PHP but for various reasons we have re-written the application in node. The code below takes the post data and then should check to see if the file exists then if it does update it if not it should create the file and directory.
However it only seems to create the first file and I cannot fathom why it doesn't create the subsequent files as this post route is called once for each post.
the post method looks like this
$.ajax({
type : "POST",
url : '/save/',
dataType : 'json',
data : {
category : settings.category_id,
name : settings.campaignId,
json : JSON.stringify(settings)
}
});
I have debugged and when called all the correct file paths are passed but its almost as if the file isn't being written with the data.
During debugging using node-inspector and nodemon the code loops through all the requested new file names and gives me the error code ENOENT, so it should then follow the create file path.
If you know anything about node and the file system module and feel like helping me out that would be amazing even if it's just pointing me in the direction of some more tutorials, ... anything would be great!
-
'use strict'
const fs = require('fs');
const path = require('path');
const express = require('express');
const router = express.Router();
/* Save Data */
router.post('/', function(req, res) {
if (!(req.body.json && req.body.name && req.body.category)) {
res.sendStatus(400);
return;
}
let dir = 'public/savedData/' + req.body.category;
let filepath = dir + '/' + req.body.name + '.json';
fs.access(filepath, function(error) {
console.log(filepath);
console.log(error.code);
if (error) {
if (error.code == 'ENOENT') {
console.log(error.code);
//debugger;
// Create file since it doesn't exist
createFile(req, res, filepath);
} else {
//debugger;
console.log('access error:', error);
res.sendStatus(500);
}
} else {
//debugger;
// Update file since it already exists
updateFile(req, res, filepath);
}
});
});
function createFile(req, res, filepath) {
try {
let json = JSON.parse(req.body.json);
let output = JSON.stringify([json], null, 4);
fs.mkdir(path.dirname(filepath), function(error) {
if (error) {
if (error.code == 'EEXIST') {
updateFile(req, res, filepath);
} else {
res.sendStatus(500);
console.log('create file error :', error);
}
} else {
fs.writeFile(filepath, output, function(error) {
if (error) {
res.sendStatus(500);
console.log('write file error :', error);
} else {
res.sendStatus(200);
console.log('Data successfully saved');
}
});
}
});
} catch (error) {
res.sendStatus(500);
console.log(error);
}
}
function updateFile(req, res, filepath) {
try {
fs.readFile(filepath, 'utf-8', function(error, data) {
if (error) {
res.sendStatus(500);
console.log('update error:', error);
} else {
try {
let newJSON = JSON.parse(req.body.json);
let jsonArray = JSON.parse(data);
let output;
jsonArray.push(newJSON);
output = JSON.stringify(jsonArray, null, 4);
fs.writeFile(filepath, output, function(error) {
if (error) {
res.sendStatus(500);
console.log(error);
} else {
res.sendStatus(200);
console.log('Data successfully saved');
}
});
} catch (error) {
res.sendStatus(500);
console.log(error);
}
}
});
} catch (error) {
res.sendStatus(500);
console.log(error);
}
}
module.exports = router;
Instead of checking if the file exists, you should try to write with flags wx, which creates a file but fails if it does already exist. That way you won't be subjecting yourself to race conditions. I would also suggest the package mkdirp, which does not emit an error if the directory already exists.
router.post('/', (req, res) => {
if (!(req.body.json && req.body.name && req.body.category)) {
res.sendStatus(400);
return;
}
const dirpath = `public/savedData/${req.body.category}`;
const filepath = `${dirpath}/${req.body.name}.json`;
mkdirp(dirpath, err => {
if (err) {
console.error('mkdirp failed', err);
return res.sendStatus(500);
}
const output = JSON.stringify([JSON.parse(req.body.json)]);
fs.writeFile(filepath, output, { flags: 'wx' }, err => {
if (err) {
console.error('writeFile failed', err);
return res.sendStatus(500);
}
console.log('Data successfully saved');
res.sendStatus(200);
});
);
});
Make sure you sanitize the req.body.name and req.body.category parameters, since you could expose your filesystem to unintentional overwrites.
Thanks to #Iso this is my solution
router.post('/', (req, res) => {
if (!(req.body.json && req.body.name && req.body.category)) {
res.sendStatus(400);
return;
}
const dirpath = 'public/savedData/' + req.body.category;
const filepath = dirpath + '/' + req.body.name + '.json';
mkdirp(dirpath, err => {
if (err) {
console.error('mkdirp failed', err);
return res.sendStatus(500);
}
const output = JSON.stringify([
JSON.parse(req.body.json)
]);
fs.readFile(filepath, 'utf-8', function(error, data) {
if(error) {
fs.writeFile(filepath, output, err => {
if (err) {
console.error('writeFile failed', err);
return res.sendStatus(500);
}
console.log('Data successfully saved');
res.sendStatus(200);
});
} else {
let newJSON = JSON.parse(req.body.json);
let jsonArray = JSON.parse(data);
let output;
jsonArray.push(newJSON);
output = JSON.stringify(jsonArray, null, 4);
fs.writeFile(filepath, output, err => {
if (err) {
console.error('writeFile failed', err);
return res.sendStatus(500);
}
console.log('Data successfully saved');
res.sendStatus(200);
});
}
});
});
});

NodeJS error when rendering page:Cast to ObjectId failed for value "styles.css" at path "_id"

The error prevents my webpage from being rendered. As mentioned in the title, the error lies in styles.css, when I take this file out, I do not get any errors.
styles.css is included in a separate headers.ejs file which is added in all pages, but there is only one route for which the error is shown(/cats/new). I put up some some logs around my routes and it seems when I enter /cats/new/, I am automatically redirected to a new route (get /cats/:id). I am wondering if this is the cause of the error?
I have attached my routes and the full error message below:
routes:
var express = require('express');
var router = express.Router();
var User = require('../models/user.js');
var Cat = require('../models/cat.js');
var Comment = require('../models/comment.js');
//middleware
function isAuthenticated(req,res,next) {
req.isAuthenticated() ? next() : res.redirect('/login');
}
router.get("/", function(req,res) {
res.redirect("cats");
});
router.get('/cats', function(req,res) {
Cat.find({}, function(err, cats) {
if (err) {
console.log(err);
} else {
res.render('cats', {cats: cats});
}
});
});
router.get('/cats/new', isAuthenticated, function(req,res) {
console.log('went to /cats/new');
res.render('new', {user: req.user});
});
router.post('/cats', isAuthenticated, function(req,res) {
console.log('went to post /cats');
var name = req.body.name;
var image = req.body.url;
var owner = req.user.username
var description = req.body.description;
cat = new Cat({
name: name,
image: image,
owner: owner,
description: description
});
cat.save();
User.findById(req.user._id, function(err, user) {
if (err) {
console.log(err);
} else {
user.cats.push(cat);
user.save();
}
})
res.redirect('cats');
});
router.get('/cats/:id', function(req,res) {
var id = req.params.id;
Cat.findById(id).populate('comments').exec(function(err, cat) {
if (err) {
console.log('entering get /cats/:id');
console.log(err);
} else {
console.log('no errror yet');
console.log(cat.comments);
res.render('show', {cat:cat});
}
});
});
router.post('/cats/:id', isAuthenticated, function(req,res) {
console.log(isAuthenticated);
var id = req.params.id;
Cat.findById(id, function(err, cat) {
console.log('findById running');
if (err) {
console.log(err);
console.log('err finding cat');
res.redirect('/cats');
} else {
console.log('before Comment.create');
Comment.create(req.body.comment, function(err, comment) {
console.log('after Comment.create');
if (err) {
console.log(err);
} else {
console.log('right after 2nd else');
comment.author.id = req.user._id;
console.log(req.user._id);
console.log(req.user.username);
comment.author.username = req.user.username;
comment.cat = id;
comment.save();
console.log('after saving comment');
cat.comments.push(comment);
cat.save();
console.log('saved cat');
User.findById(req.user._id, function(err, user) {
if (err) {
console.log(err);
} else {
user.comments.push(comment);
user.save();
console.log('saved user');
}
});
console.log(comment);
res.redirect("/cats/" + cat._id);
}
});
}
});
});
router.get('/cats/:id/edit', function(req,res) {
var id = req.params.id;
Cat.findById(id, function(err, cat) {
if (err) {
console.log(err);
} else {
res.render('edit.ejs', {cat:cat});
}
});
});
router.put('/cats/:id', function(req,res) {
console.log('beginning /cat/:id');
Cat.findByIdAndUpdate(
req.params.id, req.body.cat, function(err, updatedCat) {
if (err) {
console.log(err);
} else {
console.log('------------ req.body.cat');
console.log(req.body.cat);
console.log('------------ updated cat');
console.log('updated cat');
res.redirect('/cat/' + req.params.id);
console.log('not redirecting?');
}
});
router.delete('/cats/:id',isAuthenticated, function(req,res) {
var id = req.params.id;
console.log('YOU ARE TRYING TO DESTROY A CAT!');
Cat.findByIdAndRemove(id, function(err) {
if (err) {
console.log(err);
res.redirect('/user');
} else {
res.redirect('/user');
}
});
})
});
module.exports = router;
Error:
entering get /cats/:id
{ [CastError: Cast to ObjectId failed for value "styles.css" at path "_id"]
message: 'Cast to ObjectId failed for value "styles.css" at path "_id"',
name: 'CastError',
kind: 'ObjectId',
value: 'styles.css',
path: '_id',
reason: undefined }
It seems you’re including styles.css using a relative path in your template.
So when you navigate to /cats/:id, it tries to load /cats/styles.css.
In order to avoid that, you have to use an absolute path (e.g.: /styles.css or /public/styles.css – I’d recommend serving static files from a dedicated base path).
Go to
<head>
and change
<link rel="stylesheet" href="style.css">
to
<link rel="stylesheet" href="/style.css">

Categories