Node.js read multipart/form-data POST - javascript

Im passing a file to node.js with AJAX. the file is passed as a Base64 string and I pass it using multipart/form-data. The AJAX part work flawlessly, but I need to have said string stored on a variable in server side i.e. in Node.js. Now, on PHP this would be super easy:
$someVar = $_POST["myBase64EncodedFile"];
How can I achieve exactly that but with Node.js? I have to use Node.js and I dont want the file to be saved in some temp folder, I just need the string on a variabe. Any ideas? Thanks.

use formidable modules.
in express , you can ues it like this:
var formidable = require('formidable');
const form = new formidable.IncomingForm();
function handlerFormByEvent(req, res, next) {
form
.parse(req)
.on('fileBegin', (name, file) => {
console.time('start');
console.log('name', name);
file.path = `uploads/${file.name}`;
})
.on('progress', (accepted, total) => {
console.log(`accept:%d,total:%d`, accepted, total);
})
.on('field', (name, field) => {
console.log('field', name, field);
})
.on('file', (name, file) => {
// handle file
console.log('name', name);
console.log(file.toJSON());
})
.on('aborted', error => {
let message = error.message;
res.render('error', { message, error });
})
.on('error', err => {
console.error('Error', err);
let message = err.message;
res.status(err.status || 500);
res.render('error', { message, error: err });
})
.on('end', () => {
res.end('ok');
});
}

Related

Trying to serve a file and automatically start a download with Express

Seems like many people have ran into similar kind of problem but googling hasn't helped me so far. I'm trying to serve the file to the user and automatically prompt download on client side, but all I'm getting is "The image cannot be displayed because it contains errors.
Here is my client side code:
function downloadFile(passcode){
console.log(passcode);
const payload = {"password" : passcode.toLowerCase()}
axios.post(downloadUrl, payload, {
headers : {'Content-Type' : 'application/json'}
})
.then((res) => {
console.log(res.data)
window.open(downloadUrl + '/' + res.data)
})
}
So the user types in a passcode, and clicks on the download button and should get the appropriate file. New tab opens but file doesn't stard downloading.
Here is my server side:
const getFilePath = async (req, res) => {
const passcode = req.body.password
try {
fs.readdir(path.join(homeDir + '/uploads/' + passcode), 'utf-8',(err, files) => {
files.forEach((file) => {
const filename = passcode + '/' + file
try {
res.send(filename)
res.end()
} catch (error) {
console.log(error);
}
})
})
} catch (error) {
console.log(error);
}
}
const fileDownload = async (req, res) => {
const {dir: directory, file: fileName} = req.params
const filePath = path.join(homeDir + '/uploads/' + directory + '/' + fileName)
fs.access(filePath, fs.constants.F_OK, err => {
//check that we can access the file
console.log(`${filePath} ${err ? "does not exist" : "exists"}`);
});
res.download(filePath)
res.end()
}
I even check the file with fs.access and it returns true (it prints {filepath} exists), but the file is not served at all.
Any kind of help is much appreciated!
EDIT:
Decided to work on my front end a bit to cool off, came back and immidiatelly noticed res.end() just below send file, which ends the transmission. Removed it and it works like a charm!

Download JSON file from a node express server through my frontend

I have stored the file after uploading it to the downloads folder in my project directory.
I want to download that saved file from the frontend.
When I click on the download button, it doesn't fetch the file.
And when I go to http://localhost:5000/download on the express app, I got this error message
Error: Can't set headers after they are sent.
Express Server Code:
app.get('/download', (req, res) => {
res.send('file downloaded')
const file = './downloads/output.yml';
res.download(file, 'openapi.yml', (err) => {
if (err) {
console.log(err)
} else {
console.log('file downloaded')
}
});
});
Frontend App code:
HTML:
<button class="download-btn">download</button>
Script:
const handleDownload = async () => {
const res = await fetch("https://cors-anywhere.herokuapp.com/http://localhost:5000/download");
const blob = await res.blob();
download(blob, 'output.yml');
}
downloadBtn.addEventListener('click', handleDownload);
Folder Structure:
Update:
Server.js
const uploadFiles = async (req, res) => {
const file = await req.files[0];
console.log(file)
postmanCollection = file.path;
outputFile = `downloads/${file.filename}.yml`
convertCollection();
res.json({ message: "Successfully uploaded files" });
}
app.post("/upload_files", upload.array("files"), uploadFiles);
Anyone please help me with this.
You are already using res.send ,which sends the response headers back to client ,which ends the request response cycle ,and when you try to do res.download it throws error. Use instead
app.get('/download', (req, res) => {
const file = './downloads/output.yml';
res.download(file, 'openapi.yml', (err) => {
if (err) {
console.log(err)
} else {
console.log('file downloaded')
}
});
});
res.send('file downloaded')--->remove this line
You need to update your js code as well
const handleDownload = async () => {
const res = await fetch("https://cors-anywhere.herokuapp.com/download"); //http://localhost:5000--->this is not required
const blob = await res.blob();
download(blob, 'output.yml');
}
downloadBtn.addEventListener('click', handleDownload);

Req,File.Path remains undefined and i am using multer due to vague documentation,i cannot fully understant it?

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!");
});
}
}
);

How to use multer function in controller instead of using in route

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.

How to write a zip file from a request body to a file on Node server?

I am trying to write a node server that can receive a zip file of PDFs and JSON. In order to utilize it on the server I need to write it to a file on the server where I can call other functions on the internal data.
However with my current method, I can successfully write to a file in the server but when trying to open it in windows, I get an error "The Compressed (zipped) Folder is invalid."
I've tried directly piping the request to fs.createWriteStream with the same result as the code below
app.route('/myRoute').post(rawParser, function (req, res, next) {
let serverFileName = `${req.connection.remoteAddress.substring(7)}_${Date.now()}.zip`
let writeStream = fs.createWriteStream(`${__dirname}/${serverFileName}`, 'binary');
// console.log(req.rawBody);
writeStream.write(req.rawBody);
writeStream.end();
writeStream.on('error', err => {
logger.logger(err);
res.status = 500;
res.send("Server did not accept File");
});
writeStream.on('finish', () => {
logger.logger(`Writing to file: ${serverFileName}`);
res.status = 201;
res.send("Successfully Wrote file to server");
});
});
Here is my rawParser middleware
const rawParser = function (req, res, next) {
req.rawBody = [];
req.on('data', function (chunk) {
req.rawBody.push(chunk);
console.log(chunk)
});
req.on('end', function () {
req.rawBody = Buffer.concat(req.rawBody);
next();
});
}
I'm fairly new to node and javascript coding. I am welcome to any tips including your solutions

Categories

Resources