I'm writing an image upload in node.js, I have uploaded a file from the client:
<form id="frmImgUpload"
enctype="multipart/form-data"
action="/uploads/"
method="POST">
<input id="btnFile"
style="float:right;"
type="file"/>
<input id="btnUpload"
style="float:right;"
type="button"
value="Upload"/>
</form>
The code to perform the upload:
$("#btnUpload").click(function() {
$("#btnFile").attr("name", strCompanyKey);
$("#frmImgUpload").submit();
});
On the server I have displayed the data (just a small snippet):
[ '------WebKitFormBoundaryI206ASCJdnqVyOo0\r\nContent-Disposition: form-data; name="syberdyne"; filename="simonplatten.png"\r\nContent-Type: image/png\r\n\r\n�PNG\r\n\u001a\n\u0000\u0000\u0000\rIHDR\u0000\u0000\u0000�\u0000\u0000\u0000l\b\u0006\u0000\u0000\u0000Ԃ\b�\u0000\u0000\u0000\tpHYs\u0000\u0000\u000b\u0013\u0000\u0000\u000b\u0013\u0001\u0000��\u0018\u0000\u0000\nOiCCPPhotoshop ICC profile\u0000\u0000xڝSgTS�\u0016=���BK���KoR\u0015\b RB��\u0014�',
'*!\t\u0010J���\u0015Q�\u0011EE\u0004\u001bȠ�\u0003����\u0015Q,\f�\n�\u0007����������{�kּ������>������\u0007�\b\f�H3Q5�\f�B\u001e\u0011�������.#�\n$p\u0000\u0010\b�d!s�#\u0001\u0000�<<+"�\u0007�\u0000\u0001x�\u000b\b\u0000�M��0\u001c��\u000f�B�\\\u0001��\u0001�t�8K\b�\u0014\u0000#z�B�\u0000#F\u0001���',
What I would like to do is reassemble this data into the original file. Are they're any API's or tutorials that will help me to achieve this?
I've split the content received from the client:
var strBody = "";
request.on("data", function(chunk) {
strBody += chunk;
});
request.on("end", function() {
console.dir(strBody.split("\r\n"));
});
This results in:
[ '------WebKitFormBoundarynBkMCKI8RBvIReTF',
'Content-Disposition: form-data; name="syberdyne";filename="simonplatten.png"','Content-Type: image/png','','�PNG','\u001a\n\u0000\u0000\u0000\rIHDR\u0000\u0000\u0000�\u0000\u0000\u0000l\b\u0006\u0000\u0000\u0000Ԃ\b�\u0000\u0000\u0000\tpHYs\u0000\u0000\u000b\u0013\u0000\u0000\u000b\u0013\u0001\u0000��\u0018\u0000\u0000\nOiCCPPhotoshop ICC profile\u0000\u0000xڝSgTS�\u0016=���BK���KoR\u0015\b RB��\u0014�&*!\t\u0010J���\u0015Q�\u0011EE\u0004\u001bȠ�\u0003����\u0015Q,\f�\n�\u0007����������{�kּ������>������\u0007�\b\f�H3Q5�\f�B\u001e\u0011�������.#�001\u0000O��y���7\u0000\u0000\u0000\u0000IEND�B`�',
'------WebKitFormBoundarynBkMCKI8RBvIReTF--',
'' ]
This is just a snippet of the data, it looks like the binary data is encoded somehow, is there a routine I can call to decode it?
I've installed 'formidable', what do I parse it?
You could use multer package: https://www.npmjs.com/package/multer
Multer adds a body object and a file or files object to the request object. The body object contains the values of the text fields of the form, the file or files object contains the files uploaded via the form.
Example:
var express = require('express')
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
var app = express()
app.post('/profile', upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
// req.body will hold the text fields, if there were any
})
Formidable is "a node.js module for parsing form data, especially file uploads."
According to its documentation, you pass requests in and it allows you to access the form data conveinently via a callback function or through events.
Via optional callback:
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
// ...
});
And via events:
var form = new formidable.IncomingForm();
form.on('error', function(err) {
// ...
});
form.on('field', function(name, value) {
// ...
});
form.on('file', function(name, file) {
// ...
});
form.parse(req);
Related
I am trying to upload an image with a post request form. In my express.js server I am both using multer and urlencodedParser, because I am passing all the html inputs as a json object through the post request body plus a selection of a file, which I am handeling it with multer.
Here is the HTML code for the form:
<form action="http://localhost:8000/api/addOrgs" method="post">
<div class="form-row">
<!-- OTHER CODE -->
<div class="form-group col-md-6">
<label>Image or Logo</label>
<input type="file" class="form-control" name="image" id="fileToUpload">
</div>
<button class="btn btn-primary"> Add the organization to the system</button>
</div>
</form>
I have set up the multer:
// add image to folder
var multer = require('multer')
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '../public/images/')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
var upload = multer({ storage: storage })
Here is the express post request handler:
// to add a new organization to the list
app.post('/api/addOrgs', upload.single('imageToUpload'), urlencodedParser, (req, res)=> {
try {
var newobj = req.body;
// want to change name of id in obj
// add image name and delete image field
newobj['img'] = newobj.image;
delete newobj.image;
// read orgs file
let orgs = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../orgs.json')));
//... OTHER CODE
// send respond
res.send('<h1>Successfully added!</h1><br><p>'+JSON.stringify(newobj, null, 4)+'</p></br><b>Now you can go BACK</b>')
// OTHER CODE
} catch (e) {
// ... OTHER CODE
}
});
The problem is that I successfully have the name of the file uploaded in the json object sent through the req.body but it does NOT save the file in the folder. Is the problem coming from the usage of urlencodedParser for the app.post() parameter?
Or do I have to do something in order to save the file inside my app.post() function?
The file's form should have enctype="multipart/form-data" attribute. Try this, and it should work
So the file uploaded is an excel file that sheetJS needs to read, otherwise it will show as {}.
app.post('/sendExcel', function(req, res) {
let data = req.body;
var workbook = sheetJS.read(data, {type: 'buffer'});
console.log(workbook.Sheets['Sheet1); //prints... "{ A1: { t: 's', v: '[object Object]' }, '!ref': 'A1' }"
let excel = workbook.Sheets['Sheet1']['A1']['v'][0]; //prints... "["
So I've tried various things including changing the type client side as I had problems with it being of type buffer. So now it works partially, but I still can't access the data in the sheet.
As an example, I used the file path instead here, and it's shown to work as normal.
app.get('/excel', function(err, res, data) {
var wb = sheetJS.readFile("data.xlsx");
let excel = wb.Sheets['Sheet1']['A1']['v'];
console.log(excel); //this prints "vehicle", which is what is supposed to happen, not "[".
res.send(excel)
});
I am supposed to get the excel data from the form upload. That's the issue. It is is now successful when sending to the db, but will not access the whole data. I believe I need to change it back to an array.
You can use:
var fileReader = new FileReader();
fileReader.readAsArrayBuffer(workbook);
But this will not run in app.js
Here is my other answer with client-side and server-side. It might be helpful to others.
Javascript Read Excel file on server with SheetJS
Don't use the file reader. Append the excel sheet to the form in the body normally.
Client side:
let excelInput = document.getElementById("fileToUpload");
//excelInput: this html element allows you to upload the excel sheet to it
let excelFile = excelInput.files[0];
let form = new FormData();
form.append("excel", excelFile);
fetch('/sendExcel', {method: "POST", body: form})
.then((data) => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
Then use formidable server side.
Server side:
const sheetJS = require('xlsx');
const formidable = require('formidable');
app.post('/excel', function(req, res) {
let data = req.body;
const form = formidable({ multiples: true });
form.parse(req, (err, fields, files, next) => {
if (err) {
next(err);
return;
}
var f = files[Object.keys(files)[0]];
var workbook = sheetJS.readFile(f.path);
res.send(workbook);
});
});
So formidable has to be used otherwise it won't work. Then you can use sheetJS.readFile instead of sheetJS.read.
I'm developing a web application using nodejs server-side. I'm trying to send pdf files from client to server.
Client:
var files = new FormData();
var count = 0;
$('#tableSlideId tr').each(function() {
var inputForm = $(this).find("th:first").children();
file = inputForm[0].files[0];
files.append((count++).toString(),file);
});
$.ajax({
type: "POST",
url: "/sendFiles",
data: files,
contentType: false,
processData: false,
}).done(function(err){
var text ="";
if(err) {
text = "Upload FAILED! Retry ...";
} else {
text = "Upload SUCCES!";
}
alert(text);
});
I think the client side is ok, infact if I use this loop:
for(var p of files)
console.log(p);
I correctly visualize all the elements that I want to send to the server.
Server:
app.post('/sendFiles', function(req,res) {
console.log("--->",req.body);
res.end();
});
Now in the server I have no idea how to visualize the data that I send, infact req.body is empty.
I don't know if this is the right way but my goal is to load some pdf files form the client, send to the server and after store them in a mySql dmbs.
Thank you.
Use express-formidable module. install 'express-formidable' by the running command
npm install express-formidable --save
a simple example is as follows from github
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
console.log(req.fields);
console.log(req.files);
});
Hope this helps!
Edit, from here -
app.post('/submit-form', (req, res) => {
new formidable.IncomingForm().parse(req, (err, fields, files) => {
if (err) {
console.error('Error', err)
throw err
}
console.log('Fields', fields)
console.log('Files', files)
files.map(file => {
console.log(file)
})
})
})
I think you need some middleware to accept the multipart formdata in the server side. Multer is a good option.
You can use
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
and then update your server side to handle the upload:
app.post('/sendFiles', upload.array('files', maxCount), function(req,res)
I am sending a CSV file to my node + express server using jQuery's ajax POST method. When I post the csv file to my express route, I don't know how to access the file once it reaches the server. My goal is to pass the CSV file into my route's middleware called upload.single(). I'm also not sure which data type to specify for the ajax call.
Here is my form where I accept the CSV file:
<form onSubmit={this.handleSubmit.bind(this)} encType="multipart/form-data">
<input id="userFile" type="file" name="userFile"></input>
<input type="submit" name="submit" value="Upload New Candidates"></input>
</form>
Here is my handleSubmit function which makes the POST request:
handleSubmit(event) {
event.preventDefault();
var csvToSend = document.getElementById("userFile").files[0];
$.ajax({
type: "POST",
url: 'http://localhost:3000/',
data: csvToSend,
success: success,
dataType: //not sure what to put here
});
}
Here is my express route on the server. How should I access the CSV file sent from the client and enter it into the upload.single() middlware?
app.post('/', upload.single('userFile'), function(req, res, next) {
res.sendStatus(200);
});
As peteb mentioned it looks like you're using multer for a single file and so in that situation:
// If you set up multer to store files locally
const upload = multer({ dest: 'uploads/' });
const fs = require("fs");
app.post('/', upload.single('userFile'), async function(req, res, next) {
const filePath = req.file.path;
const fileData = await fs.promises.readFile(filePath); // Buffer of csv file
const csvString = fileData.toString();
// Do whatever you need to with the csv file
res.sendStatus(200);
});
I have file from client that i have to read on server side and send back to client for download , How can i acheive that task using nodejs. I tried with fs but i am getting some error.
console.log(data) is coming as empty object
server.js
var multiparty = require('multiparty');
var data = new multiparty.Form();
export function create(req, res) {
data.parse(req, function(err, fields, files) {
console.log(files);
var fileContent = fs.readFileSync(files.file[0].path,'utf8');
res.json(fileContent );
});
}
router.js
var express = require('express');
var controller = require('./fileUpload.controller');
var router = express.Router();
router.post('/fileUpload',controller.create);
module.exports = router;
fileData
{ file:
[ { fieldName: 'file',
originalFilename: 'sco_poc.bpmn',
path: 'C:\\Users\\9u\\AppData\\Local\\Temp\\f4DG8L7nCpNyNvVPYqGPkd44.bpmn',
headers: [Object],
size: 11078 } ] }
I am assuming you are trying download a local file the path from your JSON object 'fileData'. My example below is written in NodeJS
First, you will need to stringify your JSONobject
var jsonString = JSON.stringify({ file:
[ { fieldName: 'file',
originalFilename: 'sco_poc.bpmn',
path: 'C:\\Users\\9u\\AppData\\Local\\Temp\\f4DG8L7nCpNyNvVPYqGPkd44.bpmn',
headers: [Object],
size: 11078 } ] });
//console.log(jsonString)//print jsonString contents
Second, parse it into a JavaScript object
var jsonObj = JSON.parse(jsonString);
//console.log(jsonObj); //print jsonObj contents
Third, get path from jsonObj
var path = jsonObj.file[0].path;
Finally, read the (local) file
fs.readFile(path,function(err,data){
var fileData="";
fileData+=data;
res.writeHead(200, {
'Location': '<if needed>',
'Content-Type':'<expected content-type>'
});
res.end(fileData); //ends response, and sends to client
});
If you look at the very first example on the multiparty NPM page here: https://www.npmjs.com/package/multiparty, you will see that you need to run this for each new request, not just once that you reuse over and over:
var form = new multiparty.Form();
So, for starter move that into your request handler. Then, if you're unsure how to use the results, I'd suggest you add this:
console.log(fields, files);
And, this should show you what data you actually have.
FYI, you can see errors in the parsing with this:
form.on('error', function(err) {
console.log('Error parsing form: ' + err.stack);
});
Also, note this statement from the documentation:
If cb is provided, autoFields and autoFiles are set to true and all
fields and files are collected and passed to the callback, removing
the need to listen to any events on form. This is for convenience when
you want to read everything, but be sure to write cleanup code, as
this will write all uploaded files to the disk, even ones you may not
be interested in.
You will need to cleanup files on disk after each request or they will accumulate.