I have a express proxy server for angular application. From angular I am making post request to expressjs, there the same formData posting to backend and getting 500 as response.
app.post('/upload', upload.any(), (request, response) => {
const formData = new FormData({'file': request.file});
axios.post(loaderUrl + `/loads`, formData, {headers:formData.getHeaders()})
.then(resp => {
response.send(resp.data)
})
.catch(error => {
response.send(error);
});
});
Here request.file = {
fieldname: 'file',
originalname: 'Sample.xlsx',
encoding: '7bit',
mimetype: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
buffer: <Buffer 50 6d 6c 20 ... 46844 more bytes>,
size: 46894
}
Backend error log: "org.springframework.web.multipart.MultipartException: Current request is not a multipart request"
You need to pass the content-type header.
headers: {
Content-Type: multipart/form-data,
formData.getHeaders()
}
Backend error log: "org.springframework.web.multipart.MultipartException: Current request is not a multipart request"
The error above clearly states that the request you are sending to the server is not of the exact type that is required. The request should explicitly state its type i.e. Multipart.
You can achieve that by replacing this line of code
axios.post(loaderUrl + `/loads`, formData, {headers:formData.getHeaders()})
With
axios.post(loaderUrl + `/loads`, formData, {headers: {'Content-Type': 'multipart/form-data'}})
Related
so I have an API with an endpoint that returns an xlsx file on post request
when I call that API from nextjs server side API it returns a corrupted zip file
but when I call it directly through postman it returns the expected xlsx file.
the call to the API from nextns looks like this:
axios.post(`${process.env.API_URI}`, formData, {
headers: {
...formData.getHeaders(),
},
responseType:"blob"
}).then(response => {
res.status(200).send(response.data)
tmpObj.removeCallback()
}).catch(err => {
console.log(err)
tmpObj.removeCallback()
})
is there a proper way to receive the xlsx file in nextjs API ... Nodejs
update:
eventually I had to set the Content-Type in axios header and the responseType in axios config object
axios.post(`${process.env.API_URI}`, formData, {
headers: {
...formData.getHeaders(),
'Content-Type': 'blob',
},
responseType:"arraybuffer"
}).then(response => {
//createthe buffer in the frontend const buffer = Buffer.from(response.data, 'base64');
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
// res.setHeader('Content-Disposition', 'attachment;filename=SheetJSNode.xlsx')
res.status(200).send(response.data)
}).catch(err => {
console.log(err)
})
hi I am using express and multer to receive multiple files in backend from react frontend my react query code is like this:
fileChangeHandler = (event) => {
const data = new FormData()
let files = event.target.files
for (let file of files) {
data.append('file', file)
}
let url = db.url + "/adminendpoint/uploadfile"
axios.post(url, data, {
headers: {
'Content-Type': 'application/json',
Authorization: this.props.token
},
}).then(r => console.log(r.names))
}
the backend data for multer is like this :
uploadFile = async (req,res,next)=>{
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/images')
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' +file.originalname )
}
})
let upload = multer({storage:storage}).array('file')
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
return res.json({err:err})
} else if (err) {
return res.json({err:err})
}
let names=[]
req.files.map(f=> names.push(f.filename))
console.log(names);
res.setHeader('Content-Type', 'application/json');
return res.json({names:names})
})
but the weird thing is that in the backend the names is an array holding the names of uploaded files but in the frontend the response is an object with a lot of data like this. it has the names array in it but I want to stop sending this chunk of data from my backend and only send the file names and the response format should only be json
config: {url: "http://localhost:8090/adminendpoint/uploadfile", method: "post", data: FormData, headers: {…}, transformRequest: Array(1), …}
data:
names: (2) ["1603483842517-2.png", "1603483842518-3.png"]
__proto__: Object
headers: {content-length: "54", content-type: "application/json; charset=utf-8"}
request: XMLHttpRequest {readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, onreadystatechange: ƒ, …}
status: 200
statusText: "OK"
__proto__: Object
You're all set, just use the data property from the Axios response object.
console.log(r.data.names)
Axios returns a response object that contains more than just the response body. You'll get status, headers, config, request. The complete field list is availabel in Axios docs.
Also, a few side notes. You wouldn't want to set 'Content-Type': 'application/json' in React, since you're using FormData - it'll set 'Content-Type': 'multipart/form-data' behind the scenes. And in Express, if you're using res.json(), you don't have to set content type at all since that function already sets it.
I am trying to upload image on the server in NodeJS using multer and I was successful in my task but the thing is I want to send back the file object to the client.
Here is the some piece of the code
uploadRouter.route('/')
.post(authenticate.verifyUser, authenticate.verifyAdmin, upload.single('imageFile'), (req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
console.log(req);
res.json(req.file);
})
When I send the request in postman to the server. It is showing 200 status. File is also uploaded on the server but in postman response it's showing blank.
Here is the screenshot of postman
When I logged the req.file object it's showing undefined
but when I logged req object here is what I got
IncomingMessage {
.....
file: {fieldname: 'imageFile', originalname: 'alberto.png', encoding: '7bit', mimetype: 'image/png', destination: 'public/images', …}
.....
}
if this file object is inside the req object then why I am not able to access by req.file?
I'm trying to get/read the response from a POST request made in Angular 7, if I set the API to return "text" everything is OK, but when i make the response a JSON the response body on Angular is null.
If I try the API on Postman I get full response JSON body.
I tried changing response method on Express API (from the simple res.json() to the "old" way of declaring Content-Type and sending it with res.end()), nothing changed.
The response code I'm using on backend:
res.status(200).json({
success: true,
token: token
})
What I also tried:
res.writeHead(200, { 'Content-Type': 'application/json' })
var json = JSON.stringify({
success: true,
token: token
})
res.end(json)
The service I'm using on Angular:
login(username: string, password: string): Observable<any> {
let body = {username: username, password: password};
let headers = new HttpHeaders();
headers.set('Content-Type', 'application/json');
return this.http.post(this.baseUrl + "/login/sign-in", body, {headers: headers, responseType: 'json', observe: 'response'});
}
The call to that service:
this.api.login("admin", "password").subscribe(result => {
console.log(result);
})
On Postman I get this result:
On Angular I get this (JSON):
On Angular I get this (TEXT):
Edit:
If I add anything before the JSON on the Express app, the body is no more null:
res.writeHead(200, { 'Content-Type': 'application/json' })
var json = JSON.stringify({
success: true,
token: token
})
res.end('some_char' + json)
The result (of course the response goes in error):
Edit 2:
I'm also trying (with no luck) with this simple version of the endpoint:
const express = require('express')
const app = express()
app.post('/login/sign-in', (req, res) => res.json({ value: 1 }))
app.listen(3000, () => {
console.log('App running on port 3000.')
})
Solution:
It was all a CORS problem, I added this to the backend and everything is working fine:
app.use(cors())
Spent a few minutes trying to find out why the body would be empty,
In my case, I had "mode":"no-cors" set in my fetch() options, therefore the returned value from the server would appear as "opaque"
redux fetch body is not use with no cors mode
I hope this can help !
I am running my React js web app in one port 3000.
For node server I am using 4000.
While calling fetch method it returns `400 Bad request'.
Error
POST http://localhost:4006/auth/admin 400 (Bad Request)
react code npm started in 3000 port
fetch('http://localhost:4000/auth/admin',
{ mode: 'no-cors',
method: "POST",
body: JSON.stringify({
username:"admin",
password:"1234"
}),
headers: {
"Content-Type": "application/json",
'Accept': 'application/json, text/plain, */*',
credentials: "omit", //
// "Content-Type": "application/x-www-form-urlencoded",
},
})
.then((response) => console.log(response));
node code running in 4000 port
const passport = require("passport");
const route = require("../constants/routeStrings");
const keys = require("../config/keys");
const processStatus = require("../constants/processStatus");
const success = {
status: processStatus.SUCCESS
};
const failute = {
status: processStatus.FAILURE
};
module.exports = app => {
app.post('/auth/admin', passport.authenticate("local"), (req, res) => {
res.send(success);
});
};
Do not stringify the body. Change from
body: JSON.stringify({
username:"admin",
password:"1234"
}),
to
body: {
username:"admin",
password:"1234"
},
The 400 response is raised by passport since it is unable to read your params. You need to tell your "node" app to parse them before your actual routes.
// Import body parser, you should read about this on their git to understand it fully
const parser = require('body-parser');
const urlencodedParser = parser.urlencoded({extended : false});
// before your routes
app.use(parser .json());
app.use(urlencodedParser) // This will parse your body and make it available for your routes to use
Then do your other calls.
Also, make sure that you are sending username and password keys, otherwise read the documentation on how to change these key names to something else
I suffered long hours, but I overcame it throw writing those lines of code blocks. I successfully send the request to the server's controller, hopefully yours: make it try.
First define a async function to make POST request:
async function _postData(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
redirect: 'follow',
referrerPolicy: 'no-referrer',
headers: {
"Content-type": "application/json; charset=UTF-8"
},
body: JSON.stringify(data)
});
return response.json();
}
Now create a request JSON payload:
let requestPayload = {
propertyName1: 'property value1',
propertyName2: 'property value23',
propertyName3: 'property value',
So on
}
Note: Request model will be your desired model, what request payload you actually send.
Now make a request using this payload including your end point URL:
_postData('http://servername/example', requestPayload )
.then(json => {
console.log(json) // Handle success
})
.catch(err => {
console.log(err) // Handle errors
});
100% worked on my project.