How to get multipart/form-data? - express

when I submit the form to the Submit form button, everything works and the uploaded file is logged into the server console, but why does the Multipart: Boundary not found error occur when I click on Submit using fetch
const express = require("express");
var bodyParser = require("body-parser");
const app = express();
const multer = require("multer");
const fileStorageEngine = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "./images");
},
filename: (req, file, cb) => {
cb(null, Date.now() + "--" + file.originalname);
},
});
const upload = multer({ storage: fileStorageEngine });
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(bodyParser.text());
app.get("/", (req, res) => {
res.send(`
<form action="/push" method="POST" enctype="multipart/form-data">
<input type="file" name="image" />
<button type="submit">Submit form</button>
<button onclick="send(event)" type="submit">Submit using fetch</button>
</form>
<script>
function send(event) {
event.preventDefault();
let formData = new FormData(event.currentTarget.parentElement);
fetch("/push", {
body: formData,
headers: {
"Content-Type": "multipart/form-data",
},
method: "POST",
}).then((data) => console.log(data));
}
</script>
`);
});
app.post("/push", upload.single("image"), (req, res) => {
console.log(req.file);
});
app.listen(3000);

I suppose you want to upload an image? to do so you will need to pass three parameter in your fetch request uri , type and name in your formdata. as an exemple :
fetch("/push", {
body: {uri :formData.uri ,
type: formData.type,
name: forData.name}
headers: {
"Content-Type": "multipart/form-data",
},
method: "POST",
}).then((data) => console.log(data));
}

Related

How to implement conditional upload file using multer?

I have 2 input type="file" on a single form and I want file from left input upload into "left" folder and right to "right"
but how could I know what file was uploaded from right or left input?
const express = require("express");
var bodyParser = require("body-parser");
const app = express();
const multer = require("multer");
app.get("/", (req, res) => {
res.send(`
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="left"/><br>
<input type="file" name="right" /><br>
<button type="submit">send</button>
</form>
`);
});
app.post("/upload", function (req, res, fields) {
const storage = multer.diskStorage({
destination: function (req, file, cb) {
if (true /*if from input name left*/) {
cb(null, "left");
} else {
//if from input name right
cb(null, "right");
}
},
filename: (req, file, cb) => {
cb(null, file.originalname);
},
});
const upload = multer({
storage: storage,
}).fields([{ name: "left" }, { name: "right" }]);
upload(req, res, (err) => {
if (err) throw err;
});
});
app.listen(3000);
You are using an upload with fields like this const upload = multer({ storage: storage, }).fields([{ name: "left" }, { name: "right" }]);
and it is supposed for the field names to be identical to form-data appended values,
so all you need to do is to access the request files correctly like following:
for the 'left' file input you access the uploaded file with:
req.files['left'][0]
and for the 'right' file input you also can access it the same way:
req.files['right'][0]
[

cant get current User from API with axios

i have a problem to get my auth User. When I call my route where the current user is in i become no Data in my Vue file.
Backend:
var app = express();
app.use(cors({
methods:['GET','POST'],
credentials: true,
}))
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser('test'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(session({
secret: 'test',
resave: true,
saveUninitialized: true,
}))
app.use(passport.initialize());
app.use(passport.session());
const port = 3000
app.use(express.static('public'))
//Passport setup
const apiRoutes = require('./apiRoutes')
app.use('/api', apiRoutes)
Passport config:
passport.use(new LocalStrategy(
{
usernameField: 'username',
passwordField: 'password'
},
function(username, password, done) {
userModel.findOne({
username: username
}, (req, res) => {
const match = bcrypt.compare(password, res.password).then(result => {
if (result) {
return done(null, res, {message: 'hat geklappt'})
} else {
return done(null, false, {message: 'hat nicht geklappt'})
}
})
})
}
));
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
Route:
router.get("/", (req, res) => {
let user = req.user;
res.json(
user
);
});
My API is not empty but i cant get the data from Axios get
API:
APi
and my Empty data field:
vue
i dont know what i can do because i have not so much experience and iam really thankfull for help
Thanks :)
set content-type: application/json in the header like this:
it's a sample
var axios = require('axios');
var data = JSON.stringify({"username":"username","password":"password"});
let domain = "localhost";
let port = "3000"
let url = `http://${local}:${port}/api`
var config = {
method: 'post',
url: '',
headers: {
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
the request is not added to the question, but you can change your request base on my answer

fetch POST request is pending (sending data from registration form)

I know that similar questions have already been here, but I didn't find anything for my problem.
I am creating project using [Webpack-Express-Pug-VanillaJS] stack of technologies.
I'm trying to make POST-request to send formData to '/api/users' using fetch a push data to array in my express file, but its only pending...
What kind of problems it can be?
client-side code
document.addEventListener('DOMContentLoaded', () => {
async function postData(url, data) {
try {
console.log('addEventListener works!')
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
console.log('fetch works!')
return await response.json()
} catch(e) {
console.warn('Error',e.message)
}
}
const forms = document.getElementsByTagName('FORM');
for (let i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(e) {
console.log(forms[i])
e.preventDefault();
let formData = new FormData(this);
formData = Object.fromEntries(formData);
console.log(formData) return object like {name:'Zhanna', age:25, email:'123zhanna#gmail.com'}
postData('/api/users', formData).then(data => console.log('Successful!'))
})
}
})
server-side
const path = require('path')
const express =require('express')
const webpack = require('webpack')
const bodyParser = require('body-parser')
const users = require('../routes/userInfo')
import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import config from '../../webpack.dev.config.js'
import { v4 } from 'uuid';
const PORT = process.env.PORT || 8080
const app = express(),
compiler = webpack(config)
app.use(users.router);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.json());
app.set('views', path.join(__dirname, "views"));
app.set('view engine', 'pug');
app.locals.basedir = __dirname;
app.use('/assets',express.static(path.join(__dirname,'assets')))
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
})
)
app.use(webpackHotMiddleware(compiler))
app.get('/registration', (req,res)=> {
res.status(200).render('registration')
})
app.get('/login', (req,res)=> {
res.status(200).render('signIn')
})
app.get('/', (req, res) => {
res.status(200).render('index')
}
)
app.get('/api/users', (req,res)=> {
res.status(200).json(users.list)
})
app.post('/api/users', (req,res)=> {
const user = {...req.body, id:v4()}
users.list.push(user)
console.log('Data was sent')
res.status(201).json(user)
})
app.listen(PORT, () => {
console.log(`App listening to ${PORT}....`)
console.log('Press Ctrl+C to quit.')
})
And in my console there is only 3 logs:
addEvent listener works!
<form class="registration--form" id="send-form">...<form>
3.{name: "Zhanna", surname: "Kaymedenova", gender: "female", brth: "07.01.1994", email: "zh.kaymed#gmail.com"}

Success upload file via postman but fail on front-end (vue)

I have been success upload file via postman and file has been moved to the folder, but when I try on front-end (vuejs) nothing error but file is not moved,
_upload(){
let fd = new FormData();
fd.append('photo', this.photo); // this.photo is base64 data
this.axios.post('upload_photo', fd, {
headers: {
'content-type': 'multipart/form-data'
}
}
).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
}
try this:
First create the variable.
var photo = ref();
bind to input file tag
<input
id="photo"
type="file"
name="photo"
hidden
#change="previewImage"
#input="photo= $event.target.files[0]"
/>
This is the upload function
const uploadImg = () => {
var formData = new FormData();
formData.append("photo", photo);
(async () => {
await axios
.post(route("editImg"), formData, {
headers: {
Accept: "application/json",
"X-Requested-With": "XMLHttpRequest",
"Content-Type": "multipart/form-data",
},
credentials: "same-origin",
})
.then((response) => {
console.log(response);
.catch((e) => {
console.log("err = ", e);
});
})();
};

VueJS and express pass csrf token to post

I use VueJS (cli 3) & axios, and NodeJS - ExpressJS in the back-end. I am trying to secure my post user edit using CSRF token.
Vue View (edit user - focus to mySubmitEd):
<template>
<div class="one-user">
<h1>this user</h1>
<h2>{{name}} - {{surname}} - {{ perm }}</h2>
<h2>Edit</h2>
<input type="text" v-model="name">
<input type="text" v-model="surname">
<input type="text" v-model="perm">
<button #click="mySubmitEd">Edit</button>
<button #click="mySubmit">Delete</button>
</div>
</template>
<script>
import axios from 'axios'
import io from 'socket.io-client'
export default {
name: 'one-user',
data () {
return {
name: '',
surname: '',
perm: '',
csrf: '',
id: this.$route.params.id,
socket: io('localhost:7000')
}
},
mounted () {
axios.get('http://localhost:7000/api/get-user/' + this.id)
.then(res => {
const data = res.data.user
this.name = data.name
this.surname = data.last_name
this.perm = data.permalink
this.csrf = res.data.csrfToken
axios.defaults.headers.common['X-CSRF-TOKEN'] = this.csrf
})
.catch(error => console.log(error))
},
methods: {
mySubmit () {
const formData = {
_id: this.id
}
axios.post('http://localhost:7000/api/delete-user', formData)
.then(this.$router.push({ name: 'get-user' }))
.catch(error => console.log(error))
},
mySubmitEd () {
const formData = {
_id: this.id,
name: this.name,
last_name: this.surname,
permalink: this.perm,
_csrf: this.csrf
}
console.log(formData._csrf)
axios.post('http://localhost:7000/api/update-user', formData)
.catch(error => console.log(error))
}
}
}
</script>
server.js file:
...
const cookieParser = require('cookie-parser');
const csurf = require('csurf');
...
app.use(cookieParser());
const csrfProtection = csurf({ cookie: true });
app.use(csrfProtection);
...
back-end controller which get the user:
controller.getOneUser = function(req, res) {
User.findOne({ _id: req.params.userId }).exec(function(err, user) {
res.json({user, csrfToken: req.csrfToken()});
});
};
back-end update post:
controller.updateUser = function(req, res) {
User.findById(req.body._id, function(err, user) {
user.set({
name: req.body.name,
last_name: req.body.last_name,
permalink: req.body.permalink,
price: req.body.price
});
user.save();
res.send(user);
});
};
My errors in NodeJS-exress console:
ForbiddenError: invalid csrf token
My errors in browser:
POST http://localhost:7000/api/update-user 403 (Forbidden)
I don't know what is happened because I see in network tab(chrome) the csrf token is the same in the headers and what I send (ex.):
X-CSRF-TOKEN: PddyOZrf-AdHppP3lMuWA2n7AuD8QWFG3ta0
_csrf: "PddyOZrf-AdHppP3lMuWA2n7AuD8QWFG3ta0"
I don't know what I have miss here. I can't find where is the problem.
If you want more information please asked me to help you.
I had to pass in the headers the cookie correctly, so I did 2 corrections:
First in Vue view:
I passed credentials:
axios.create({withCredentials: true}).get(...)
and
axios.create({withCredentials: true}).post(...)
and secondly in server.js file before routes I put this:
...
const corsOptions = {
origin: 'http://localhost:8080',
credentials: true,
}
app.use(cors(corsOptions));
app.use(bodyParser.json());
app.use(cookieParser());
const csrfProtection = csurf({ cookie: true });
app.use(csrfProtection);
app.use(function (req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken());
res.locals._csrf = req.csrfToken();
next();
});
...