I am making a put request from frontend for which I have been using XMLHttpRequest and FormData API request but server side I would not get any data like req.params, req.body and req.query all are empty
Front-end Code
var reportSub = () => {
var report = document.getElementById('report');
var formData = new FormData(report)
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.response)
}
}
var queryString = new URLSearchParams(formData);
xhr.open("PUT", '/threads/edit', true);
xhr.setRequestHeader('Content-Type', 'multipart/form-data');
xhr.send(queryString)
}
var reportsub = document.querySelector('#repsub');
reportsub.addEventListener("click",(e)=>{
e.preventDefault();
reportSub();
})
Server Side code
router.put('/threads/edit',(req,res)=>{
let board = req.body.board;
let id = req.body.id;
console.log(req.query,req.body)
Board.findById({_id: ObjectId(id)},(error,data)=>{
if(error)
res.send(error)
if(data!==null){
data.Reprot = true;
data.save((error,sd)=>{
if(error)
res.send(error)
res.send(sd);
})
}
else{
res.send({"Error":"Id does not exist "})
}
})
})
There is one solution would be where you add data in url which again hard coded each in every variable and data you had to pass.
So thats I want use FormData interface for sending data.
I think you are missing a library for parsing the FormData request. You could also send the data using JSON as it is text-only, this would simplify parsing. A minimal example could look like the following:
server.js
const express = require("express");
const multer = require("multer");
const upload = multer();
const app = express();
app.use(express.static('public'))
app.post('/data', upload.none(), function (req, res) {
console.log(req.body.favoriteNumber);
res.send('42 is the only real choice');
});
app.listen(3000, function () {
console.log('App listening on port 3000!');
});
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form id="textForm">
<p>Your favorite number:</p>
<input type="text" value="42" name="favoriteNumber" />
</form>
<button id="send">Send</button>
<script>
const sendButton = document.getElementById("send");
const form = document.getElementById("textForm");
sendButton.addEventListener("click", () => {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.response);
}
}
const formData = new FormData(form);
xhr.open("POST", '/data', true);
xhr.send(formData);
})
</script>
</body>
</html>
You do not have to set the header manually. It is set automatically and does include boundary - a parameter you cannot know while writing the application. The header could look like the following:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryuzeaYvzY77jzcFeA
Related
Im trying to get an local txt file from calling a XMLHttpsRequest() method. But it keeps sending me a 404 error message in the console. Please help me out.
here is my html file
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Ajax1</title>
</head>
<body>
<button id="button" type="button" name="button">Get text files</button>
<script type="text/javascript">
document.getElementById("button").addEventListener('click', loadText)
function loadText(){
var xhr = new XMLHttpRequest();
xhr.open('GET', 'sample.txt', true);
xhr.onload = function(){
if(xhr.status === 200){
console.log(xhr.responseText)
}
}
xhr.send(null);
}
</script>
</body>
</html>
Local txt file is not inside any folder.
I dont know whether this is important or not but here is my app.js file
const express = require('express')
const app =express()
app.use(express.static("public"))
app.get('/', function(req, res){
res.sendFile(__dirname+'/ajax1.html')
})
app.listen(3000, function(){
console.log('server is runing')
})
here is my directory tree
`>Ajax-beginning
>node_modules
•Ajax.html
•app.js
•package-lock.jason
•package.jason
This is my javascript function which is routing a csv file to /uploader.
function getData() {
var csv=document.getElementById('myFile').files[0];
var formData=new FormData();
formData.append("uploadCsv",csv);
var request = new XMLHttpRequest();
//Open first, before setting the request headers.
request.open("POST", "/uploader", true);
//here you can set the request header to set the content type, this can be avoided.
//The browser sets the setRequestHeader and other headers by default based on the formData that is being passed in the request.
request.setRequestHeader("Content-type", "multipart/form-data"); //----(*)
request.onreadystatechange = function (){
if(request.readyState === XMLHttpRequest.DONE && request.status === 200) {
console.log(request.response);
}
}
request.send(formData);
}
My python function does get invoked to the app routing part seems to correct. However the request.files length is 0.
This is the python code -
#app.route("/uploader", methods=["POST"])
def post_javascript_data():
f = request.files["uploadCsv"]
print(f)
return "OK"
In the picture below you can see the request.files length remains 0. What am I doing wrong here?
The solution is to not manually set the header for the content type. This is set automatically.
The following is an example with XMLHttpRequest and alternatively with fetch.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!-- Using XMLHttpRequest -->
<form name="upload-form-1">
<input type="file" name="upload-csv" accept="text/csv" />
<input type="submit" />
</form>
<script type="text/javascript">
(function() {
let form = document.querySelector("form[name='upload-form-1']");
form.addEventListener(
"submit",
(event) => {
event.preventDefault();
let xhr = new XMLHttpRequest();
xhr.open("POST", "/uploader");
xhr.onload = function() {
if(this.status === 200) {
console.log(this.response);
} else {
console.error(`Error ${this.status} occurred.`)
}
}
xhr.send(new FormData(event.target));
},
false);
})();
</script>
<!-- Using Fetch -->
<form name="upload-form-2">
<input type="file" name="upload-csv" accept="text/csv" />
<input type="submit" />
</form>
<script type="text/javascript">
(function() {
let form = document.querySelector("form[name='upload-form-2']");
form.addEventListener(
"submit",
(event) => {
event.preventDefault();
fetch("/uploader", {
method: "POST",
body: new FormData(event.target)
}).then(resp => {
console.log(resp);
}).catch(err => {
console.error(err);
});
},
false);
})();
</script>
</body>
</html>
from flask import abort, make_response, request
#app.route('/uploader', methods=['POST'])
def uploader():
if 'upload-csv' in request.files:
f = request.files['upload-csv']
# Use the object of the type werkzeug.FileStorage here.
return make_response('')
abort(400)
Have fun implementing your project.
I'm trying to print the data which has been received at the server side but it always
shows a blank body output printing req={}
I've been trying for days and I can't find the answer, any help would be greatly appreciated!!!
the server side code:
const express= require('express');
const app=express();
const data_itself = require('./data.js');
app.use(express.static('public'));
app.use(express.urlencoded({extended:true}));
app.listen(3100,()=>{
console.log('sever listening at port 3100...')
});
app.set('view engine','ejs');
app.set('views','public');
app.get('/',(req,res)=>{
res.redirect('/home');
});
app.post('/',(req,res)=>{
var random_data='recived post request!'
res.send(random_data);
console.log('req=',req.body); //this outputs to req={}
});
The client side code:
<!DOCTYPE html>
<head>
<title>Sample Site</title>
</head>
<body>
<button onclick="send_info()">Submit data</button>
<div id="stat"></div>
</body>
<script>
data=['xyz'];
function send_info(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("stat").innerHTML =
this.responseText;
}
};
xhr.open("POST",'/', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
}
</script>
</html>
You need to have your express server use the JSON parser middleware. Add the following line to your server file.
app.use(express.json())
An explanation of the middleware is available at this link: http://expressjs.com/en/api.html
I have a webpage I am trying to allow a video to be sent to my API via XMLhttprequest as below:
<form onsubmit="submitBtn()">
<input type="file" accept="video/*" name="fileupload" value="fileupload" id="fileupload">
<label for="fileupload"> Select a file to upload
</label>
<input type="submit" value="submit">
</form>
<script language="javascript" type="text/javascript">
function submitBtn() {
var search = document.getElementById('fileupload').value;
if (search.length>0){
var text = search;
userAction(text);
}
}
</script>
<script language="javascript" type="text/javascript">
function userAction(res) {
var formData = new FormData();
formData.append("video", res);
var request = new XMLHttpRequest();
var api = 'myApi'
request.open('POST', api, true);
request.onload = function () {
// Begin accessing JSON data here
var data = this.response;
if (request.status >= 200 && request.status < 400) {
console.log('celebrate');
} else {
console.log('error');
}
}
request.send(formData);
}
</script>
This part seems to work fine, however, I don't believe the video itself is sent to my API. If I context.log(result.body) I get something similar to:
------WebKitFormBoundary1234
Content-Disposition: form-data; name="video"
C:\fakepath\videoname.mp4
------WebKitFormBoundaryq1234--
I wish to then send this video to another API as multipart/form body content.
I have attempted this by using:
function videoAPI (context, auth, vid, callback){
var body = vid;
var requestUrl = urlApi;
const requestOptions = {
hostname: requestUrl.hostname,
path: requestUrl.path,
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
}
};
var request = https.request(requestOptions, function(res) {
var data = "";
res.on('data', function (chunk) {
context.log('Response: ' + chunk);
data += chunk;
});
res.on('end', function () {
var jsonData = JSON.parse(data);
callback(jsonData);
});
})
request.write(body);
request.end();
}
Again, this functions, however, the response I get is:
Input is invalid. Input must specify either a video url, an asset id or provide a multipart content body
This seems to suggest that I am either not sending the video correctly, or I am not sending it correctly via the XMLhttprequest.
Can someone highlight where I have gone wrong and how to correct it please?
I am using nodejs and Azure.
Using javascript, I want to read xml file from the disk, modify the values/add elements/attributes and save the xml back to disk.
Anyone knows here can i find examples that works with IE and Firefox? I allready find examples to read, now changing values that's the problem.
Thanks
Assuming you are trying to read and write to disk from the browser and not node.js,
the first step is to use an input tag of type file to get access to the file system.
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
</head>
<body>
<input type="file" id="input" accept="text/xml">
<script src="script.js"></script>
</body>
As soon as a file is selected we want to extract the blob from the element.
A good moment to do that is during the change event.
const input = document.querySelector('#input');
input.addEventListener('change', () => {
const file = input.files.item(0);
});
There is more than one way to parse the blob into a tree of elements.
Here I took advantage of the fact that the browser parses xml documents in HTTP requests.
function blobToDocument(blob, callback) {
const url = URL.createObjectURL(blob);
const request = new XMLHttpRequest();
request.open('Get', url);
request.responseType = 'document';
request.addEventListener('load', () => {
callback(request.response);
});
request.send();
}
After the blob has been parsed we can manipulate it like we would manipulate the DOM tree.
function editDocument(document) {
const element = document.createElement('editor');
element.textContent = 'JavaScript';
document.firstChild.appendChild(element);
return document;
}
In order to save the file to disk we need to reverse the process of parsing,
converting the tree of elements back to a string.
function documentToString(document) {
const serializer = new XMLSerializer();
return serializer.serializeToString(document);
}
The only thing left is to send the file back to disk.
To achieve this we can trigger a click event on a link with our modified file.
function download(string, mime) {
const blob = new Blob([string], { type: mime });
const a = document.createElement('a');
const url = URL.createObjectURL(blob);
a.href = url;
a.download = 'document.xml';
a.click();
}
Here is the complete code
const input = document.querySelector('#input');
input.addEventListener('change', () => {
const file = input.files.item(0);
blobToDocument(file, (xmlDocument) => {
editDocument(xmlDocument);
download(documentToString(xmlDocument), "text/xml");
});
});
function blobToDocument(blob, callback) {
const url = URL.createObjectURL(blob);
const request = new XMLHttpRequest();
request.open('Get', url);
request.responseType = 'document';
request.addEventListener('load', () => {
callback(request.response);
});
request.send();
}
function editDocument(document) {
const element = document.createElement('editor');
element.textContent = 'JavaScript';
document.firstChild.appendChild(element);
return document;
}
function documentToString(document) {
const serializer = new XMLSerializer();
return serializer.serializeToString(document);
}
function download(string, mime) {
const blob = new Blob([string], { type: mime });
const a = document.createElement('a');
const url = URL.createObjectURL(blob);
a.href = url;
a.download = 'document.xml';
a.click();
}
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
</head>
<body>
<input type="file" id="input" accept="text/xml">
<script src="script.js"></script>
</body>