multipart/form-data possible to send with javascript? - javascript

I am sending a file over POST together with text "name" using this form:
<form enctype="multipart/form-data" action="https://site[DOT]net/upload" method="post">
<input id="name" type="text" />
<input id="data" type="file" />
<button type="submit" name="submit" />
</form>
I would like to do the exect same using javascript. In addition I dont want to be redirected. I want to stay on the html page and just show a popup "Upload done". How can I do this in javascript (no jquery)?
EDIT:
I tried this code but the POST is not working:
<script>
function uploader {
var formData = new FormData();
formData.append("name", "Smith");
formData.append("data", fileInputElement.files[0]);
var request = new XMLHttpRequest();
request.open("POST", "https://site[DOT]net/upload");
request.send(formData);
}
</script>
<form>
<input id="name" type="text" />
<input id="data" type="file" />
<button type="submit" name="submit" />
<button onclick="uploader()">Click</button>
</form>

In case any wants to do this with the new fetch instead of xhr this is the equivalent. Also see: How do I POST with multipart form data using fetch?
var form = document.getElementById('formid');
form.onsubmit = async (e) => {
e.preventDefault();
const form = e.currentTarget;
const url = form.action;
try {
const formData = new FormData(form);
const response = await fetch(url, {
method: 'POST',
body: formData
});
console.log(response);
} catch (error) {
console.error(error);
}
}
<form id="formid" enctype="multipart/form-data" action="#" method="post">
<input id="name" type="text" />
<input id="data" type="file" />
<button type="submit" name="submit">Submint</button>
</form>

Uploading the entire form with javascript, including the files, can be done by using the FormData API and XMLHttpRequest
var form = document.getElementById('myForm'); // give the form an ID
var xhr = new XMLHttpRequest(); // create XMLHttpRequest
var data = new FormData(form); // create formData object
xhr.onload = function() {
console.log(this.responseText); // whatever the server returns
}
xhr.open("post", form.action); // open connection
xhr.send(data); // send data
If you need to support IE10 and below, it gets increasingly complicated, and would in some cases require posting through iFrames etc.

Related

How Do I Post A Form Without Redirecting Using Raw Javascript?

I've seen several posts about how to post a form using AJAX, but I am curious about options for simplification.
Here's a trimmed down version of what I'm trying:
<form id="message-form" method="POST" action="/send-message" onsubmit="return false;">
<input type="text" name="message"><br/>
<input type="text" name="phone_number"><br/>
<button type="button" onclick="return trysubmit()">Send Message</button>
</form>
<script>
function trysubmit()
{
document.getElementById("message-form").submit();
//notify user of success
//cancel the redirect
return false;
}
</script>
In this case, the form gets submitted, but the redirect still happens.
Is something like the above even possible, or do I have to manually build an AJAX request like this?
form serialize javascript (no framework)
var form = document.getElementById('message-form');
var data = new FormData(form);
var req = new XMLHttpRequest();
req.send(data);
Unless resorting to hacks like posting to a dummy target, AJAX is the way to go.
This works:
const form = document.querySelector("#message-form");
form.addEventListener("submit", event => {
event.preventDefault()
let status = "";
const data = new FormData(form);
const req = new XMLHttpRequest();
try{
req.open("POST", '/send-message');
req.send(data);
status = "success";
}
catch{
status = "failure";
}
notifyuser(status);
});

Javascript formData array returns empty

I have an issue with my AJAX formData object. If select a file in the input and I send this with AJAX the array is empty. I hope somebody can help me with this. Below my code
HTML and JavaScript
<form method="post" id="quoteform">
<input type="file" name="uploadfile" id="quote"/>
<input type="submit" value="upload"/>
</form>
<script type="text/javascript">
document.getElementById("quoteform").addEventListener("submit", function(){
var files = document.getElementById("quote").files;
var formData = new FormData();
for (var i = 0; i < files.length; i++) {
var file = files[i]
formData.append('files[]', file);
}
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "linktophpfile.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send('upload='+formData);
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
alert(this.responseText);
}
}
event.preventDefault();
});
</script>
PHP
<?php
if(isset($_POST['upload'])){
print_r($_FILES);
}
?>
The PHP file returns
Array
(
)
when you upload files then you can't use application/x-www-form-urlencoded you have to use multipart/form-data
you shouldn't mix strings with formData send('upload='+formData) it will only result in you uploading a string equal to upload=[Object object]
you should instead just send the formData and let the XHR or Fetch handle the content-type for you automatically.
If you want an array then i presume you also want the attribute mulitple? You could always add in the required and accept="image/*, .txt" for good measure
You don't manually have to add in all files to a formdata if you just use the first constructor argument that accepts a form element, everything from the form will be added
<form method="POST" action="https://httpbin.org/post" id="quoteform" encoding="multipart/form-data">
<input multiple type="file" name="files[]" id="quote" required />
<input type="submit" value="upload"/>
</form>
<script>
// html (xml) should mark the settings, behavior as it mostly always have done
// in all years way back and the js should provide enhancement and
// be more generally written to enhance the site (if js where
// to be turned off - most unlikely, I for once have it disabled in my phone)
// static sites works better without ads + annoying cookie popups
// it's a good thing Brave have quick toggle to enable scrips for js-only pages
function ajaxify (evt) {
evt.preventDefault()
var form = evt.target
var formData = new FormData(form)
fetch(form.action, {
method: form.method,
body: formData
}).then(res => res.text()).then(alert)
}
document.getElementById("quoteform").addEventListener("submit", ajaxify)
</script>

Post method with ajax

I would like to send the data to another php page using javascript but it does not work as expected.
Let just say I have the form:
<form id="myForm">
<label for="name">Username</label>
<input type="text" name="name" id="name">
<label for="pass">Password</label>
<input type="password" name="pass" id="pass">
<button id="submit" type="submit" >OK</button>
</form>
and the script:
const myForm = document.getElementById('submit');
myForm.addEventListener('submit', function(e){
e.preventDefault();
const data = new FormData(this);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'getData.php', true);
xhr.onload = function () {
// do something to response
console.log(this.responseText);
};
xhr.send(data);
});
The php file is unable to recieve the data at the moment. How can it fix with ajax or any other equivalent code?
Make change in button
<button id="submit" type="button" onclick="sendData()" >OK</button>
Then add javascript function.
<script>
function sendData(){
var name = document.getElementById("name");
var password = document.getElementById("pass");
if (name) {
$.ajax({
type:"POST",
url:"path-to-php-file.php",
data:'name='+name+'&pass='+password,
success:function(data){
alert(data);
}
});
}
</script>
Then create php file where you will get data.
path-to-php-file.php
<?php
$name = $_POST['name'];
$password = $_POST['pass'];
echo $name .'--'.$password;
?>
I cannot tell exactly what is the problem without looking at your php code.
Maybe there is something wrong with the Content-Type header.
document.getElementById('submit').addEventListener('submit', (e) => {
e.preventDefault();
const data = new FormData(this); // Here 'this' will not work, you gotta loop through the inputs and append them to the FormData object.
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
// do something
}
xhr.open('POST', 'getData.php', true);
// the default content type is application/x-www-form-urlencoded
xhr.setRequestHeader("Content-Type", "<content type here>")
xhr.send(data);
});
Extra
What I suggest is in your case you won't really need a form element here. You could make the button a normal button and make the form a div(not special benefit, just for clean code). Assign a function to the onclick event of the button and loop through the inputs and append them to the form data(if the content type is application/x-www-form-urlencoded) object and send it to the server.Use this method if you have a complex form like a interactive form like Google or Microsoft have.
And also you do not want to use preventDefault() method if you follow my method.
This is what most professionals would do.

How to make my HTTP request behave the same as a form

I'd need some help with my HTTP request. Here's the setup:
A webpage load an image to a form and send it to a python server running bottle (with the form or a custom http request)
Bottle receive the file, give it as an input for a python script, receive the result and return it to the webpage
On bottle's website there's an example with a form: https://bottlepy.org/docs/dev/tutorial.html#file-uploads I've tried it and it works. Here's the code I used:
<html>
<head>
</head>
<body>
<form action="http://localhost:8080/solve" method="POST" enctype="multipart/form-data" norm="form" id='myForm'>
Select a file: <input type="file" name="upload"/>
<input type="submit" value="Start upload" />
</form>
</body>
</html>
In bottle I have:
#route('/solve', method='POST')
def solve():
file = request.files.get('upload')
name, ext = os.path.splitext(file.filename)
if ext not in ('.png','.jpg','.jpeg'):
return 'File extension not allowed.'
print(file.name)
resolved = sudoku.solve(file.file)
return str(resolved)
This "works", but the form redirects me to localhost:8080 and it's not what I want. I tried putting the target to a hidden iFrame, which prevent the redirection, but I don't manage to access the result in the body of the iFrame...
What I want: Make an HTTP request similar to the one made by the form. So I tried:
<html>
<head> </head>
<body>
<form enctype="multipart/form-data" norm="form" id="myForm">
Select a file:
<input id="fileInput" type="file" name="upload" accept="image/png, image/jpeg, image/jpg" />
<input type="submit" value="Start upload" />
<label class="button-upload" onclick="send()">Upload</label>
</form>
</body>
<script>
var _file = null;
function send() {
var file = document.getElementById("fileInput").files[0]
console.log(file)
var url = "http://localhost:8080/solve";
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader(
"Content-Type",
"multipart/form-data; boundary=---------------------------169461201884497922237853436"
);
var formData = new FormData();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
formData.append("upload", file);
xhr.send(formData);
}
</script>
</html>
I've checked with the developper tool in network and the request seems to be the same as the one sent by the form, though bottle can't find the file.
The file = request.files.get('upload') returns None and file = request.files returns <bottle.FormsDict object at 0x7ff437abf400> so there's something but I don't understand how to access it!
Any help would be greatly appreciated!
Your JavaScript code seems fine, except for where you set request headers with xhr.setRequestHeader. FormData handles multipart encoding for you, you don't need to set request headers manually. I just tried it, and it seems to be working fine with bottlepy.
Overall, change your send() function as follows:
function send() {
var file = document.getElementById("fileInput").files[0]
console.log(file)
var url = "http://localhost:8080/solve";
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
var formData = new FormData();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
formData.append("upload", file);
xhr.send(formData);
}

AJAX form upload not grabbing file - AJAX/jQuery

I am not sure if I am grabbing the file from the form correctly in the following jQuery code which uses AJAX to upload a file.
function uploadFile() {
console.log("uploading");
var form = document.getElementById('fileForm');
var fileSelect = document.getElementById('browseInput');
console.log("check1");
var file = fileSelect.files;
var formData = new FormData();
formData.append('FileInput', file, file.name);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'default/ParseExcel', true);
xhr.send(formData);
console.log("complete");
}
I get the error that file is undefined on line 39 (which is the formData.append() line in the code above.
I'm not sure if I am supposed to be grabbing the file form the form variable or from the fileSelect variable.
The full error:
TypeError: Argument 2 of FormData.append does not implement interface Blob.
HTML code:
<form enctype="multipart/form-data"
method="POST"
id="fileForm"
onsubmit="uploadFile()"
style="display:inline-block;">
<input id="browseInput" type="file" name="FileInput" style="display: none"/>
<label for="upload-click-handler"></label>
<input id="upload-click-handler" type="text" readonly />
<button id="submitFormButton" type="submit" style="display: none"></button>
</form>
Try this:
function uploadFile(e) {
e.preventDefault();
var formElement = document.getElementById('fileForm');
var formData = new FormData(formElement);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'pack.php', true);
xhr.send(formData);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form enctype="multipart/form-data" method="POST" id="fileForm" onsubmit="uploadFile(event)">
<input id="browseInput" type="file" name="FileInput" />
<button id="submitFormButton" type="submit">Submit</button>
</form>
Output using var_dump($_FILES);
array (size=1)
'FileInput' =>
array (size=5)
'name' => string '3400.JPG' (length=8)
'type' => string 'image/jpeg' (length=10)
'tmp_name' => string 'E:\wamp\tmp\php38E2.tmp' (length=23)
'error' => int 0
'size' => int 164319

Categories

Resources