I'm trying to use ytdl-core module in order to download youtube audio to my local disk (some path on my computer).
I created an API to which I can call with the requested youtube url and the destination folder in which I want the file to be saved.
app.get('/api/downloadYoutubeVideo', function (req, res) {
var videoUrl = req.query.videoUrl;
var destDir = req.query.destDir;
ytdl.getInfo(videoUrl, function(err, info){
var videoName = info.title.replace('|','').toString('ascii');
var stream = ytdl(videoUrl, { filter: 'audioonly'})
.pipe(fs.createWriteStream(destDir + '\\' + videoName + '.mp3'));
stream.on('finish', function() {
res.writeHead(204);
res.end();
});
});
});
The problem is that when I call the api on my localhost (example: localhost:11245/api/downloadYoutubeVideo?videoUrl=https://www.youtube.com/watch?v=E5kJDWQSBUk&destDir=C:\test)
it works and the file indeed downloads to "C:\test".
But when I call to the api on my remote (example: http://sometest.cloudno.de/api/downloadYoutubeVideo?videoUrl=https://www.youtube.com/watch?v=02BAlrAkuCE&destDir=C:\test)
it doesnt create the file in the directory...
I have searched the answer but haven't found one...
Does C:\test already exist on your remote? If not you can't use fs.createWriteStream() until the directory has been created, it will not create the directory for you implicitly. Since you're not listening for an 'error' event, you wouldn't even know that was the problem since you're not capturing it.
The below code sample will check for the existence of destDir and if it doesn't exist will create it before proceeding.
const fs = require('fs');
const sep = require('path').sep;
function checkAndMakeDir(dir, cb) {
fs.access(dir, (err) => {
if (err)
fs.mkdir(dir, (err) => {
if (err)
return cb(err);
return cb();
});
else
return cb();
});
}
app.get('/api/downloadYoutubeVideo', function (req, res) {
let videoUrl = req.query.videoUrl;
let destDir = req.query.destDir;
checkAndMakeDir(destDir, (err) => {
if (err) {
res.writeHead(500);
return res.end();
}
ytdl.getInfo(videoUrl, function (err, info) {
let videoName = info.title.replace('|', '').toString('ascii');
let saveStream = fs.createWriteStream(`${destDir}${sep}${videoName}.mp3`);
saveStream.once('error', (err) => {
console.log(err);
res.writeHead(500);
return res.end();
});
saveStream.once('finish', () => {
res.writeHead(204);
return res.end();
});
ytdl(videoUrl, {filter: 'audioonly'})
.once('error', (err) => {
console.log('Read Stream Error', err);
res.writeHead(500);
return res.end();
})
.pipe(saveStream);
});
});
});
Related
I,m using mutler to upload a image and i am constantly getting this error.
And i think the following function triggers it.
The complete js code is attached below.Thanks in advance!
const upload = multer({
dest: "/uploads"
});
app.post(
"/game",
upload.single("file" /* name attribute of <file> element in your form */),
(req, res) => {
const tempPath = req.file.Path;
const targetPath = path.join(__dirname, "/uploads/"+imgname+".jpg");
imgname++;
if (path.extname(req.file.originalname).toLowerCase() === ".jpg") {
fs.rename(tempPath, targetPath, err => {
if (err) return handleError(err, res);
res
.status(200)
.sendFile(__dirname + '/game.html');
});
} else {
fs.unlink(tempPath, err => {
if (err) return handleError(err, res);
res
.status(403)
.contentType("text/plain")
.end("Only .jpg files are allowed!");
});
}
}
);
Js file link: https://filebin.net/fd7q89ji16xftst4
Your code doesn't have a variable called imgname. After checking the code, it looks like you need to pass the file name for the imgname. You can use req.file.filename to get the name of the uploaded file.
Full code:
const upload = multer({
dest: "/uploads"
});
app.post(
"/game",
upload.single("file" /* name attribute of <file> element in your form */),
(req, res) => {
const tempPath = req.file.Path;
const imgname = req.file.filename;
const targetPath = path.join(__dirname, "/uploads/"+imgname);
imgname++;
if (path.extname(req.file.originalname).toLowerCase() === ".jpg") {
fs.rename(tempPath, targetPath, err => {
if (err) return handleError(err, res);
res
.status(200)
.sendFile(__dirname + '/game.html');
});
} else {
fs.unlink(tempPath, err => {
if (err) return handleError(err, res);
res
.status(403)
.contentType("text/plain")
.end("Only .jpg files are allowed!");
});
}
}
);
I want to Use multer function in controller file But the problem is req.body got undefine when I use postman form-data body to upload images This is link to code that how I am using multer Function but I want use it in my controller
how I want to use it as you can see in below code
const multerHelper = require("../helpers/multer_helper");
Documents: async (req, res) => {
console.log(req.body)
if (!req.body.id) {
console.log(req.body)
logger.warn(error.MANDATORY_FIELDS);
return res.status(500).send(error.MANDATORY_FIELDS)
}
try {
multerHelper.createUserImage
let result = error.OK
logger.info(result);
return res.status(200).send(result)
} catch (err) {
logger.warn(err);
console.log(err);
return res.status(500).send(error.SERVER_ERROR)
}
}
but it throws error like req.body undefine
req.body empty image
postman form-data image
Anyone know how to do it
You can use multer functions and objects in only routes not in controller if you want to use it in controller you have to write storage and upload functions in controllers, here I have used multer error handling and I am uploading multiple images
Documents: async (req, res) => {
if (!req.headers.room_id) {
logger.warn(error.MANDATORY_FIELDS);
return res.status(500).send(error.MANDATORY_FIELDS)
}
try {
let storage = multer.diskStorage({
destination: function (req, file, cb) {
let id = req.headers.room_id;
let path = `tmp/daily_gasoline_report/${id}`;
fsextra.mkdirsSync(path);
cb(null, path);
},
filename: function (req, file, cb) {
// console.log(file);
let extArray = file.mimetype.split("/");
let extension = extArray[extArray.length - 1];
cb(null, file.fieldname + '-' + Date.now() + "." + extension);
}
})
var upload = multer({ storage: storage }).array('images', 100);
upload(req, res, function (err) {
if (err) {
console.log(err);
return res.end("Error uploading file.");
} else {
res.end("File has been uploaded");
}
});
let result = error.OK
logger.info(result);
return res.status(200).send(result)
} catch (err) {
logger.warn(err);
console.log(err);
return res.status(500).send(error.SERVER_ERROR)
}
}
Do you have a parser?
How do you parse the data?
Your gonna need to use something that gives you this data something like:
https://www.npmjs.com/package/express-fileupload
this package helps you to parse the form data and the files data itself.
app.post('/profile', function(req, res) {
// save file
if (req.files) {
let sampleFile = req.files.sampleFile;
sampleFile.mv('/somewhere/on/your/server/filename.jpg', function(err) {
if (err)
return res.status(500).json(err);
});
}
// do some other stuff
// .............
res.status(200).json(result);
});
I know the problem is caused by return res.status(500).json(err). I can solve the problem by moving res.status(200).json(result) after if (err) block. Since upload file is optional, the user may posting other data without any uploading files. My question is how to send status 200 with a json result after processed other stuff if the solution is
if (err)
return res.status(500).json(err);
res.status(200).json(result);
As was pointed above the problem is you are sending the success reponse outside of the callback.
The solution is to do "other stuff" within the callback.
This should fix the issue -
app.post('/profile', function(req, res) {
// save file
if (req.files) {
let sampleFile = req.files.sampleFile;
sampleFile.mv('/somewhere/on/your/server/filename.jpg', function(err) {
if (err) return res.status(500).json(err);
doOtherStuff();
res.status(200).json(result);
});
} else {
doOtherStuff();
res.status(200).json(result);
}
});
// Write a do other stuff function
function doOtherStuff() {
// do stuff
}
EDIT Adding answer with Promises to avoid code repetition.
function moveFile(file, somePlace) {
return new Promise((resolve, reject)=>{
file.mv(somePlace, function(err) {
if (err) return reject(err);
resolve();
});
});
}
app.post('/profile', function(req, res) {
// save file if present
const fileMovePromise = req.files ?
moveFile(req.files.sampleFile, '/somewhere/on/your/server/filename.jpg')
:
Promise.resolve('No file present');
fileMovePromise
.then(() => {
// do other stuff
})
.catch(err => {
res.status(500).json(err);
});
});
You could use a form of middleware to check if the post is uploading files, the act on the file upload before continuing, have a look at middleware with express here: http://expressjs.com/en/guide/using-middleware.html
With middleware you can do your check to see if the file needs uploading and then call next, otherwise just call next.
app.use('/profile', function (req, res, next) {
if (req.files) {
let sampleFile = req.files.sampleFile;
sampleFile.mv('/somewhere/on/your/server/filename.jpg', function(err, data) {
if (err) {
res.status(500).json(err);
} else {
req.data = data
next()
}
});
}
res.status(200);
}, function (req, res) {
res.status(500).json(req.data);
})
If you are using Node for express, the res param contains res.headersSent, which you can check if the headers have already been sent.
if(res.headersSent) {}
You can also find out a lot more here: https://nodejs.org/api/http.html#http_response_headerssent
I have a child process that is being called as follows:
server.js
app.get('/search', function (req, res) {
var cp = spawn('node', 'app.js');
cp.stdout.on('data', function(data) {
console.log('stdout: ' + data);
});
...
});
Currently app.js is utilizing chrome-headless' captureScreenshot function to generate a screenshot, which is then stored locally.
app.js:
const img = await Page.captureScreenshot({format: 'png', fromSurface: true});
fs.writeFile('./screenshot.png', img.data, 'base64', function (err) {
if (err) {
console.log(err);
}
});
It is not necessary to store the image locally, but rather upload it to a server. I am trying to find a way to get this functionality to work:
server.js V2
app.get('/search', function (req, res) {
var cp = spawn('node', 'app.js');
cp.stdout.on('data', function(data) {
upload_image(data);
});
...
});
app.js V2
const img = await Page.captureScreenshot({format: 'png', fromSurface: true});
//EXPOSE 'img' to parent via cp.stdout - How do I do this part?
});
You can send messages via fork()
server.js
const { fork } = require('child_process');
app.get('/search', function (req, res) {
const forked = fork('app.js');
forked.on('message', (data) => {
uploadImage(data.imageURL); // It will be send by parent.
}); ...
});
app.js
const img = await Page.captureScreenshot({format: 'png', fromSurface: true});
fs.writeFile('./screenshot.png', img.data, 'base64', function (err) {
if (err) {
console.log(err);
}
process.send({ imageURL: './screenshot.png' }); //You can send any data from here.
});
Here is the nice tutorial for you.
https://medium.freecodecamp.org/node-js-child-processes-everything-you-need-to-know-e69498fe970a
I hope it helped you.
I write server side application with express & node.js.
I have the next:
app.configure(function () {
app.use(express.bodyParser());
});
Everything works good, but:
As I understand, this method was deprecated.
The next method doesn't work well. It writes some random chars instead of writing the correct chars:
app.post('/randomWrite', function (req, res) {
var fileName = req.body.name;
var contentLength = parseInt(req.files.file._writeStream.bytesWritten);
var start = parseInt(req.body.chunk) * 102400;
var buffer = new Buffer(parseInt(req.files.file._writeStream.bytesWritten));
fs.open(req.files.file.path, 'r', function (status, fd) {
if (fd == null) {
console.log("Can't open the file with the fd");
return;
}
fileNameLocation = "./" + fileName;
fs.open(fileNameLocation, 'w+', function (err, fd1) {
fs.read(fd, buffer, 0, contentLength, start, function (err, bytesRead, buffer1) {
if (err)
console.log("ERROR: " + err);
fs.write(fd1, buffer1, 0, contentLength, start, function (err, bytesWrite, buffer) {
if (req.body.chunk == req.body.chunks - 1) {
fs.close(fd, function (err) {
})
fs.close(fd1, function (err) {
})
FileServer.prototype.returnResCodeWithId(res, 200, id);
} else {
fs.close(fd, function (err) {
})
fs.close(fd1, function (err) {
})
FileServer.prototype.returnResCode(res, 200);
}
})
})
})
})
Instead of writing in the correct offset, it seems that something get wrong and some text from the middleware (bodyParser) is written.
How can i change the express.bodyParser()? It will fix my problem with the writing?
You need to use the Body-parser middleware.
You can install it with
npm install body-parser
and include it with Express using
var bodyparser = require('body-parser');
app.use(bodyparser());
If you want file uploads too, then have a look at multer.