issue in react code for sending data to multer - javascript

I was trying to send image to backend(multer) I checked multiple times the backend code seems correct,is there a issue in my front end code ? POST code snippet
const response = await fetch('http://localhost:5000/api/users/signup',{
method:'POST',
headers:{
'Content-Type': 'application/json'
},
body:JSON.stringify({
name: data.get('name'),
email: data.get('email'),
password: data.get('password'),
image:data.get('image')
})
});
full auth.js code https://pastebin.com/MHdDRtAX

I think you'd want to use FormData object.
const input = document.querySelector('input[type="file"]');
const body = new FormData();
body.append('image', input.files[0]);
body.append('name', data.get('name'));
body.append('email', data.get('email'));
body.append('password', data.get('password'));
// add more items as needed
const response = await fetch(URL, { method:'POST', body });

You have a content type mismatch. When using multer, you need use 'Content-Type': 'multipart/form-data'.
The basic idea is to use the FormData object.
Example below
const data = new FormData(event.target)
const response = await fetch('http://localhost:5000/api/users/signup',{
method:'POST',
headers:{
'Content-Type': 'multipart/form-data'
},
body: data
});
In network tab you will find form data with key-value
image should be a file(binary)
in multer, example code like below
var express = require('express')
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
var app = express()
app.post('api/users/signup', upload.single('image'), function (req, res, next) {
// req.file is the `image` file
// req.body will hold the text fields, if there were any
})

Related

Why is my fetch() sending an empty JSON body?

I've been trying to send a JSON data using fetch but the backend receives an empty object.
In my Client JS I have
const user = "company1";
const username = "muneeb";
const data = {user, username};
fetch("http://127.0.0.1:3000/users/api/login", {
method: 'POST',
body: JSON.stringify(data)
}).then((response) => {
console.log(response);
});
The server side has:
router.post('/users/api/login', async (req, res, next) => {
try {
// console.log(request.body);
const request = JSON.stringify(req.body);
let imageTitles = [];
console.log(request);
*its random from here on out but you get the idea*
await components.getImages(imageTitles);
const finalKey = imageTitles.join("");
let images = await components.output(req.body.user ,req.body.username);
res.send(components.jsonConverter(imageTitles, images)); //---Top priority
db.setPassword(req.body.user, req.body.username , finalKey);
} catch (err) {
console.log(err);
res.send(err).sendStatus(500);
};
})
A few things I have already tried :
It works perfectly in Insomnia(postman).
express.json() is present , it helped me go from undefined to blank JSON.
I have enabled cors settings.
That's it for now.
The body parser express.json will only be applied for requests with Content-Type: application/json. You have to add the content type to your fetch call:
fetch("http://127.0.0.1:3000/users/api/login", {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
})

CURL Command to NodeJS - PUT Request OctetStream

I need to make this curl command into a nodejs request, either using fetch, request or axios networking libraries
The request needs to PUT the file data to the URL
curl -v -H "Content-Type:application/octet-stream" --upload-file C:/Users/deanv/Pictures/test3.mp4 "https://www.example.com/file/upload"
I've tried using CurlConverter to convert my curl command to node code, but this doesn't work as I cant add the file data.
var fetch = require('node-fetch');
fetch('https://www.example.com/file/upload', {
method: 'PUT',
headers: {
'Content-Type': 'application/octet-stream'
}
});
All help appreciated. Thanks in advance.
Try this:
// setup modules
const fetch = require('node-fetch');
const FormData = require('form-data');
const fs = require('fs');
const path = require('path');
// setup paths
const pathToFile = 'C:/Users/deanv/Pictures/test3.mp4';
const uploadUrl = 'https://www.example.com/file/upload';
// create form, 'content-type' header will be multipart/form-data
const form = new FormData();
// read the file as stream
const fileStream = fs.createReadStream(path.resolve(pathToFile));
// add the file to the form
form.append('my_file', fileStream);
fetch(uploadUrl, {
method: 'PUT',
body: form
}).then((res) => {
console.log('done: ', res.status);
return res.text();
})
.then((res) => {
console.log('raw response: ', res);
})
.catch(err => {
console.log('err', err);
});

Express js request body is not excatcly i want

Im working on simple app that allows you to register new user. I managed to create fetch POST request and catch it with express app.post method. It works but the value that req.body is retruning is not plain object but something more that I want.
It's literally returning something like this : { '{"login":"fff","password":"sss"}': '' }
But I want it to be just sth like this: {"login":"fff","password":"sss"}
Here is my client side code
function eventListener() {
const formSubmit = document.querySelector('.register-form');
const newUser = new Register();
formSubmit.addEventListener('submit', (e) => {
e.preventDefault();
newUser.checkInputs();
const form = e.target;
const formData = new FormData(form)
const userData = {
login: formData.get('login'),
password: formData.get('password'),
}
console.log(userData);
fetch('/register', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: JSON.stringify(userData)
})
.then(response => {
console.log(response);
})
})
}
document.addEventListener('DOMContentLoaded', eventListener)
And here is server code
const express = require('express');
const path = require('path');
const app = express();
app.use(express.json())
app.use(express.urlencoded({
extended: true
}))
app.use(express.static('static'))
app.post('/register', (req, res) => {
console.log('ok');
console.log(req.body);
res.end();
})
app.listen(process.env.PORT || 5000, () => {
console.log('running...');
})
Don't lie to the server:
'Content-Type': 'application/x-www-form-urlencoded'
You are sending JSON.
By telling the server you are NOT sending JSON, you are confusing it.
It is trying to parse it as application/x-www-form-urlencoded
Tell it you are sending JSON:
'Content-Type': 'application/json'

Javascript fetch(POST) to express server fails. The server does not receive the request from JS, but receives request from Postman

MRE -> node-server : react app
When I send a POST request using Postman, I get the expected result. This is the request that I am sending using Postman
and test sent gets printed to the console of my node server
If I send a request from my react form however, test sent does not print to the console, but the catch block of my fetch request get's executed and err is printed to the console of my react app, followed by {}.
I would like to know why my POST request is not working and is not getting received by the server
Below is the function that I call when someone clicks the submission button of my form created in react
Function called on form submission
nodeUrl = 'https://localhost:6060?'
const submitData = async () => {
fetch(nodeUrl, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({'test': 'test'})
}).then((res) => {
alert('then')
}).catch((err) => {
alert('err')
alert(JSON.stringify(err))
})
}
}
This is the server that I run using node server.js
server.js
server.post('/', function(req, res) {
console.log('test sent')
mailer.messages().send(req.body)
.then((mes) => {
console.log(mes)
res.json({ message: 'Thanks for your message. Our service team has been notified and will get back to you shortly.' })
}).catch(err => {
console.log(err)
res.json(err);
})
});
The majour issue here is due to CORS. CORS support can be used to overcome this. Just keep in mind to have this only for development mode(see below codes).
But, as per the Postman's snapshot and provided GitHub repositories, the request from Front-end should be of multipart/form-data type. Thus, the Front-end code would look like this
const nodeUrl = "http://localhost:6060/";
const submitData = async () => {
// create a FormData object
const formData = new FormData();
formData.append('form', 'example#email.com');
formData.append('to', 'example#email.com');
// this auto adds 'multipart/form-data' + HASH header in the request
fetch(nodeUrl, {
method: "POST",
body: formData
})
.then(res => {
console.log(res);
}).catch(err => {
console.log('Error -', err);
});
};
To handle multipart/form-data request in the ExpressJS, you need a plugin Multer.
const express = require('express');
const bodyParser = require('body-parser');
const multer = require('multer'); // for 'multipart' type request
const server = express();
const upload = multer();
// allow CORS requests in development mode
if (process.env.NODE_ENV === 'development') {
// Server run command - "NODE_ENV=development node server.js"
const cors = require('cors');
server.use(cors());
}
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({extended: true}));
// using Multer middleware form extracting 'FormData' payload
server.post('/', upload.none(), function(req, res) {
console.log('Received body', req.body);
... // other codes
});
Strategy 2(plain JSON) -
If that 'multipart/form-data' strategy was unintentional and you just want to send simple JSON, use below codes -
In Front-end, trigger API request as -
fetch(nodeUrl, {
method: "POST",
headers: {
'Content-Type': 'application/json', // this needs to be defined
},
body: JSON.stringify({ from: 'some#email.com', to: 'other#email.com' })
})
In server, just ignore codes related to Multer and only keep your API as -
server.post('/', function(req, res) {
console.log('Received body', req.body);
... // other codes
});
I ended up using a better fetch request, which was put together for me by selecting code -> Javascript Fetch in Postman(under the save button)
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("from", "example#email.com");
urlencoded.append("test", "test");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
};
fetch("http:localhost:6060/, requestOptions)
.then(response => {
if (response.ok){
response.json().then(json => {
console.log(json)
})
}
})
.catch(error => console.log('error: ', error))

Uploading File via API Using NodeJS 'fetch'

I am using an existing API call to send a file to our cloud provider via Nodejs. I have seen several different methods of doing this online, but figured I would stick to using "fetch" as most of my other API calls have been using this as well. Presently, I keep getting 500 internal server error and am not sure why? My best conclusion is that I am not sending the file properly or one of my pieces of formdata are not resolving correctly. See the below code:
const fetch = require("node-fetch");
const formData = require("form-data");
const fs = require("fs");
var filePath = "PATH TO MY FILE ON SERVER WITH FILE NAME";
var accessToken = "Bearer <ACCESS TOKEN>;
var url = '<API URL TO CLOUD PROVIDER>';
var headers = {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
'Authorization': accessToken
};
const form = new formData();
const buffer = fs.readFileSync(filePath);
const apiName = "MY_FILE_NAME";
form.append("Content-Type", "application/octect-stream");
form.append("file", filePath);
console.log(form);
fetch(url, { method: 'POST', headers: headers, body: form })
.then(response => response.json())
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
});
This my first time attempting something like this so I am next to certain I am missing something. Any help with getting me in the right direction is appreciated.
So the issue was exactly what I mentioned above. The code was not uploading the file I specified. I finally figured out why and below is the modified code which will grab the file and upload to our cloud service provide:
const fetch = require("node-fetch");
const formData = require("form-data");
const fs = require("fs");
var apiName = process.env['API_PATH'];
var accessToken = "Bearer" +" "+ process.env['BEARER_TOKEN'];
var url = process.env['apiEnv'] +"/" +"archive";
var headers = {
'Accept': 'application/json',
'Authorization': accessToken,
};
const form = new formData();
const buffer = fs.readFileSync(apiName);
const uploadAPI = function uploadAPI() {
form.append("Content-Type", "application/octet-stream");
form.append('file', buffer);
fetch(url, {method: 'POST', headers: headers, body: form})
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
});
};
uploadAPI();
Being new to Javascript/Nodejs I wasn't really sure what the "buffer" variable did. After finally figuring it out I realized I was adding too many body form params to the request and the file was not being picked up and sent to the provider. All code above is using custom variables, but if for whatever reason someone wants to use it, then simply replace the custom variables with your own....Thanks again for any and all assistance....
import fs from 'fs'
import FormData from 'FormData';
const fileStream = fs.createReadStream('./file.zip');
const form = new FormData();
form.append('key', fileStream, 'file.zip');
const response = await axios.post(url, form, {
headers: {
...form.getHeaders(),
},
});

Categories

Resources