How to rename file using express-formidable package - node.js

Can't figure out on how to rename the file using the express formidable package
server.js contents:
const express = require('express')
const fs = require('fs')
const app = express()
const formidableMiddleware = require('express-formidable')
app.use(formidableMiddleware({
uploadDir: __dirname + '/public/files',
multiples: true,
keepExtensions: true
}))
router.route('/send/:mail')
.post((req, res) => {
let file = null
if (req.files) {
file = fs.readFileSync(req.files.file.path)
}
// here's the code to send email with mailgun js wrapper
})
Purpose of my code is to rename uploaded file, then send it as attachment via mailgun wrapper, however i'm stuck at the step of renaming the file using fs.rename() - i just don't know where to put it. Do i need to use node-formidable package together with express-formidable?

Solved using fs.renameSync:
fs.renameSync(req.files['files[0]'], req.files['files[0]'].name)

Related

How to request a csv file from a url via nodejs?

I'm looking for a way to request a csv file from any url to save it then. If possible only using fs, http, request and express modules.
For testing I tried it with
request('http://localhost:3000/data1.csv').pipe(fs.createWriteStream('data2.csv'))
but i always get as a resonse (data2.csv)
<pre>Cannot GET /data1.csv</pre>
Simplified Code
const fs = require('fs')
const request = require('request')
const express = require('express')
const app = express()
app.listen(3000)
app.get('/download', (req, res) => {
request('http://localhost:3000/data1.csv').pipe(fs.createWriteStream('data2.csv'))
})
The file data1.csv is saved in the root of my project folder. But is this also the root of my nodejs server from where I started it?
What I'm doing wrong here?
Thanks!
You need to have an explicit handler that returns data1.csv:
app.get('/data1.csv', (req, res) => {
res.sendFile('data1.csv');
});

NodeJS: Files only update after restarting the express server

I am using nodejs with express for a small backend application which just returns a json file from another directory.
Example scenario:
My json files are in the directory "/var/data", so e.g. "/var/data/hello.json". If I start the nodejs backend with "node index.js" everything works as expected.
But if I change the contents of a json file, I still get the old version from the backend.
How can I set this up, so that my backend nodejs server detects these file changes in another directory without restarting it?
index.js:
const express = require('express');
const fs = require('fs');
const app = express();
app.use(express.json());
const myDataPath = "/var/data/";
app.get("/:id", (request, response) => {
let id = request.params.id;
let path = myDataPath + id + ".json";
if (fs.existsSync(path)) {
response.json(require(path));
} else {
response.sendStatus(404);
}
});
Issue is likely with using "require", this is a guess, but maybe require doesn't run twice for optimization reasons.
const express = require('express');
const fs = require('fs');
const app = express();
app.use(express.json());
const myDataPath = './var/data/';
app.get('/:id', (request, response) => {
let id = request.params.id;
let path = myDataPath + id + '.json';
console.log(path);
if (fs.existsSync(path)) {
response.json(JSON.parse(fs.readFileSync(path)));
} else {
response.sendStatus(404);
}
});
app.listen(1025);
The above code snippet worked on my testing example, I used readFileSync to retrieve the data, uncached, and the response changes when the file is modified, without needing to restart the app.

node formidable rename directory path from form fields

I need to set the file upload path based on form field values in a formidable form upload that has both the file and fields ( multipart form type).
theForm.on('fileBegin', function (name, file){ ...}
is called before
theForm.parse(req, function(err, fields, files) { ... }
However, it seems that the form upload path must be set before the form fields are parsed. And so I don't see a way to access properties in fields yet. Theres nothing there yet except for prototype. I also looked in req.body but the values aren't there either.
Is this correct? Is there a way to change the form upload path after the form fields are available, but before the file is then saved to disk?
I am using the most current of everything as of today, 7/31/2017.
I also have body-parser in use, to read in JSON.. Could that be causing this issue? ( I've read that it is and also is NOT okay to use it- removing it causes other issues for me, so I've left it in so far .. )
const bodyParser = require('body-parser');
const jsonParser = bodyParser.json();
Many thanks!
I would suggest to use the express-fileupload module:
var express = require('express');
var app = express();
var path = require('path');
const fileUpload = require('express-fileupload');
app.use(fileUpload());
var defaultDir = "C:\\temp";
app.post('/upload', function(req, res){
// The name of the input field (i.e. "clientfile") is used to retrieve the uploaded file
let sampleFile = req.files.clientfile;
var savefile_path = path.join(defaultDir, req.body.path, sampleFile.name);
// Use the mv() method to place the file somewhere on your server
sampleFile.mv(savefile_path, function(err) {
if (err)
{
return res.status(500).send(err);
}
});
res.status(200).send("File uploaded");
console.log("File uploaded");
});

res.download(NodeJS) not triggering a download on the browser

I've been struggling with this for a while and can't seem to find an answer, I'm developing a website with a budgeting option, I'm sending an object from the client to the server, and that server is using PDFKit to create a PDF version of the budget, once it's created I want to actually send back that PDF to the client and trigger a download, this is what I've done
Client-side code:
let data = {
nombre: this.state.name,
email: this.state.email,
telefono: this.state.phone,
carrito: this.props.budget.cart,
subTotal: this.props.budget.subTotal,
IVA: this.props.budget.tax,
total: this.props.budget.subTotal + this.props.budget.tax
}
axios({
method: 'post',
url: 'http://localhost:1337/api/budget',
data: data
})
.then((response) => {
console.log('This is the response', response);
window.open('/download')
})
.catch((error) => {
alert(error);
})
So that data goes to my server-side code perfectly and it looks like this
const pdf = require('pdfkit');
const fs = require('fs');
const path = require('path');
exports.makePDFBudget = (req, res) => {
let myDoc = new pdf;
myDoc.pipe(fs.createWriteStream(`PDFkit/budget.pdf`));
myDoc.font('Times-Roman')
.fontSize(12)
.text(`${req.body.name} ${req.body.phone} ${req.body.email} ${req.body.cart} ${req.body.subTotal} ${req.body.total} ${req.body.tax}`);
myDoc.end()
}
That's creating my PDF, what I want now is that once it's created and the response is sent back to the client, the client opens a new window with the URL "/download" which is set to download that PDF, but that's not happening for some reason, it opens up the new window but the download never starts and it throws absolutely no error I'm my Node console or browser console
this is how I send my file to the client
const fs = require('fs');
const path = require('path');
exports.downloadPDFBudget = (req, res) => {
res.download(__dirname + 'budget.pdf', 'budget.pdf');
}
And this is how my server index looks like
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
const api = express.Router();
const { makePDFBudget } = require('./PDFkit/makePDFBudget.js');
const { downloadPDFBudget } = require('./PDFkit/downloadPDFBudget.js')
app.use(express.static(__dirname + '/../public'));
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json({extended: true}));
api.route('/budget')
.post(makePDFBudget)
api.route('/download')
.get(downloadPDFBudget)
app.use('/api', api);
const port = 1337;
app.listen(port);
console.log('Listening on port ', port);
module.exports = app;
I just solved it, the port in which I was running my client obviously was different from the one I was running my server, so I had to open a window to my server's port to trigger the download, I realized this because I threw a console log on the function that was supposed to do the res.download it wasn't showing up. Thanks!
I guess the main problem here:
res.download(__dirname + 'budget.jpg', 'budget.pdf');
Make a correct file name. Your file is pdf, not jpg.
At this code res.end(Buffer.from('budget.pdf')) you sending string, not file content. But headers like you want to send a file.
The last. Your application designed like you will have only one user. Could you add userId to file names? Or use DB for storing data and generate pdf on request without storing a file to the file system.

Parsing Post Form Data Node.js Express

I am getting form data in this form
'------WebKitFormBoundarysw7YYuBGKjAewMhe\r\nContent-Disposition: form-data; name': '"a"\r\n\r\nb\r\n------WebKitFormBoundarysw7YYuBGKjAewMhe--\r\n
I'm trying to find a middleware that will allow me to access the form data like:
req.body.a // -> 'b'
I've tried
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
Is there a problem with my implementation or am I not using the correct middleware?
The tool that worked was multiparty
app.post('/endpoint', function (req, res) {
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
// fields fields fields
});
})
The library which worked for me was express-formidable. Clean, fast and supports multipart requests too.
Here is code from their docs
Install with:
npm install -S express-formidable
Here is sample usage:
const express = require('express');
const formidable = require('express-formidable');
var app = express();
app.use(formidable());
app.post('/upload', (req, res) => {
req.fields; // contains non-file fields
req.files; // contains files
});
The above two answers are correct but now those methods are outdated. multer is a better method to access form data. Install it by the following command: npm install multer
some useful body parsers.
Body-type: parser
form-data: multer
x-www-form-urlencoded: express.urlencoded()
raw: express.raw()
json: express.json()
text: express.text()
-better to use multer.
-But if you want to use bodyParser.urlencoded convert it into URLSearchParams data type
demonstration:-
let fd=new FormData("id_of_form")
let sp=new URLSearchParams()
for(let [k,v]:fd.entries()) sp.append(k,v)
make header 'Content-Type':'application/x-www-form-urlencoded ' and pass sp to body.
-happy coding

Resources