Access file upload field from ajax - javascript

I have a problem with accessing file upload field
//HTML
<input type='file' name='images' id="images" multiple>
//////////////////
$('.bt-add-com').click(function(){
var formdata = new FormData();
var sessionID = 8;
var theCom = $('.the-new-com');
var theName = $('#name-com');
var theMail = $('#mail-com');
var theFile = formdata.append("images", sessionID);
if( !theCom.val()){
alert('You need to write a comment!');
}else{
$.ajax({
type: "POST",
url: "ajax/add-comment.php",
data: 'act=add-com&id_post='+<?php echo $id_post; ?>+'&name='+theName.val()+'&email='+theMail.val()+'&comment='+theCom.val()+'&file='+formdata.append("images[]", sessionID),
success: function(html){
theCom.val('');
theMail.val('');
theName.val('');
$('.new-com-cnt').hide('fast', function(){
$('.new-com-bt').show('fast');
$('.new-com-bt').before(html);
})
}
});
}
});
////RESULT
array (size=6)
'file' => string 'undefined' (length=9)
problem is when i access file upload field using formdata as code below. it display value as undefined. can't get uploaded file details

You're taking the form data object and appending it to a string. That won't work.
Don't try to build a string to pass to data, use the FormData API for all your fields, then pass the FormData object itself.
You also need to append the file data form the input instead of the number 8.
formdata.append("images", sessionID);
formdata.append("images[]", sessionID)
Don't use images and images[]. If you're using PHP, then use just images[]
Don't use sessionID, use the file.
formdata.append("images[]", document.getElementById('images').files[0]);

Related

server side unable to capture append formdata files

I have a module where user can snap a picture (which will converted into a base64 string and then to a file), and I require to upload the file into our server, but after converted the base64 into file object and append it into formData and submit the form. I found that in my backend, it unable to read the $_FILES property (refer last image), the array is empty but which suppose to have my file in there.
And checking on my formData variable, the data is append into it.
html
<form id="form" method="POST" action="smth.php" enctype="multipart/form-data">
...
<!-- some other input information -->
</form>
js
$('#form').on('submit', function(){
...
var formData = new FormData($(this)[0]);
var base64 = $('#photo').attr('src');
console.log(...formData);
console.log('before checking');
if(base64 != 'default.png'){
var file = dataUrltoFile(base64, 'photo.png'); //external function to convert base64 into file object
formData.append('photo', file);
}
console.log('after checking');
console.log(...formData);
...
});
console
smth.php
<?php ... var_dump($_POST); var_dump($_FILES); exit(); ... ?>
result
You won't be able to attach your FormData instance to the existing <form> for a normal submit (I think).
If you want to mess with the normal submit, you'll need to add HTML elements into the <form> like <input type="file">.
Otherwise, submit the data via AJAX
document.getElementById('form').addEventListener('submit', async function(e) {
e.preventDefault()
const formData = new FormData(this)
// do stuff to formData
const res = await fetch(this.action, {
method: this.method,
body: formData // automatically sets Content-type: multipart/form-data
})
if (res.ok) {
// handle response
}
})

Use javascript to rename file before upload

Let's say I have this list of forms like so:
var forms = document.getElementsByClassName('uploadImage');
each item in this list look like this:
<form method=​"post" action=​"/​upload" enctype=​"multipart/​form-data" id=​"f_x" class=​"uploadImage">
​ <input type=​"file" id=​"u_x">​
<input type=​"submit" value=​"Submit" id=​"s_x">​
</form>​
where x = [0,1,2,3,4,5]
How do I loop through this list and do two things:
1 - Rename the file name
2 - Submit the form for uploading the file
I looked for many resources online like this one: https://www.telerik.com/forums/change-file's-name-when-it's-uploaded-via-html-form, all of them are using Jquery , I need it in javascript
update :-
I figured out how to get to the input value of each form
forms[0].elements[0] this will return the first input of the first form on the list
forms[0].elements[0].value this output the value of the file input
So here is the code you linked to, and I will break it down a bit after. A lot of it is vanilla javascript.
$(document).ready(function() {
initImageUpload();
function initImageUpload() {
$("#btn-submit").click(function(e) {
e.preventDefault();
var everlive = new Everlive({
appId: "",
scheme: "https"
});
// construct the form data and apply new file name
var file = $('#image-file').get(0).files[0];
var newFileName = file.filename + "new";
var formData = new FormData();
formData.append('file', file, newFileName);
$.ajax({
url: everlive.files.getUploadUrl(), // get the upload URL for the server
success: function(fileData) {
alert('Created file with Id: ' + fileData.Result[0].Id); // access the result of the file upload for the created file
alert('The created file Uri is available at URL: ' + fileData.Result[0].Uri);
},
error: function(e) {
alert('error ' + e.message);
},
// Form data
data: formData,
type: 'POST',
cache: false,
contentType: false,
processData: false
});
return false;
});
}
});
As is mentioned, this uses jQuery $.ajax() to create an AJAX POST to the server with new FormData where the name of the file has been modified. The new FormData is then sent to the server instead of the HTML Form data.
So, when the button is clicked to submit the form, this event is prevented.
var file = $('#image-file').get(0).files[0];
This is then used to select the <input> element in jQuery and then collect the files info from the element.
var file = document.getElementById("image-file").files[0];
This can be done with JavaScript. Largely the rest of the script would be unchanged, except for the initialization and sending of POST Data via AJAX.
It might be best to create a function that you send the form to and it can then return the new form data with new name. As you did not want to provide an MCVE, it's hard to give you an example since it's not clear how the data for the new name would be create or gathered from.
function nameFile(inEl, newName){
var file = inEl.files[0];
var results = new FormData();
results.append('file', file, newName);
return results;
}
function sendFile(url, formData){
var request = new XMLHttpRequest();
request.open("POST", url);
request.send(formData);
}
sendFile("/​upload", nameFile(document.getElementById("file-image"), "UserFile-" + new Date().now() + ".jpg"));
Another issue is if you have multiple forms, and multiple submit buttons, which one will trigger all the items to get uploaded? Either way, you'd have to iterate each form (maybe with a for() loop) collect the form data from each, update the name, and submit each one, most likely via AJAX.
Hope this helps.

Sending images and text filed formdata ajax to php. images not identified by php

I have input text boxes of type text and one input text box of type file.I want to send these values to php file via ajax when a button is clicked. Everything seems well but for some crazy reason the image if not identified in the php file.
Kindly help, am out of ideas. My code is as below.
=========javascript code when a button if id=Saved is clicked====
$("#saved").on('click',function(){
$("#itemform").submit(function(e){
e.preventDefault();
});
var item_desc =document.getElementById("item_desc").value;
var item_price_type =document.getElementById("item_price_type").value;
var item_regular_price =document.getElementById("item_regular_price").value;
var item_type =document.getElementById("item_type").value;
var item_cat =document.getElementById("item_cat").value;
var taxablee =document.getElementById("taxablee").value;
var item_price_tax =document.getElementById("item_price_tax").value;
var item_offer_price=document.getElementById("item_offer_price").value;
var offer_start =document.getElementById("offer_start").value;
var offer_end =document.getElementById("offer_end").value;
var file =document.getElementById('file').value;
var price_tax="";
var formdata = new FormData();
formdata.append('file',file);
formdata.append('item_desc',item_desc);
formdata.append('item_price_type',item_price_type);
formdata.append('item_regular_price',item_regular_price);
formdata.append('item_type',item_type);
formdata.append('item_cat',item_cat);
formdata.append('taxablee',taxablee);
formdata.append('price_tax',price_tax);
formdata.append('item_offer_price',item_offer_price);
formdata.append('offer_start',offer_start);
formdata.append('offer_end',offer_end);
});
============php file to insert data into database===========
$item_desc =$_POST['item_desc'];
$item_price_type=$_POST['item_price_type'];
$item_regular_price=$_POST['item_regular_price'];
$item_type=$_POST['item_type'];
$item_cat=$_POST['item_cat'];
$taxablee=$_POST['taxablee'];
$price_tax=$_POST['price_tax'];
$item_offer_price=$_POST['item_offer_price'];
$offer_start=$_POST['offer_start'];
$offer_end=$_POST['offer_end'];
$item_image = $_FILES['file']['name'];
$folder = "../menu_images/";
$pics =time().$item_image;
//$sq="// this is my insert statment";
//$sq_insert =$conn->prepare($sq);
//$sq_insert->execute(array(//these are my array values for the insert
statment));
move_uploaded_file($_FILES["file"]["tmp_name"], $folder.$pics);
Why not use just a html form to submit your data, no need to use javascript for that.
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="Upload Image" name="submit">
</form>
var form = $('form')[0]; // You need to use standard javascript object here
var formData = new FormData(form);
var formData = new FormData();
formData.append('section', 'general');
formData.append('action', 'previewImg');
// Attach file
formData.append('image', $('input[type=file]')[0].files[0]);
$.ajax({
url: 'Your url here',
data: formData,
type: 'POST',
contentType: false, // NEEDED, DON'T OMIT THIS (requires jQuery 1.6+)
processData: false, // NEEDED, DON'T OMIT THIS
});

Uploading File via FormData

I am trying to upload a file to a Node backend that uses Multer. Multer requires the form to be submitted a specific way. If it's not submitted that way, the request.file parameter will be undefined. I have created an approach that works by using brute force. That working approach looks like this:
index-1.html:
<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
<input type="file" id="selectedFile" name="selectedFile" /><br/><br/>
<input type="submit" value="Submit" id="btnSubmit"/>
</form>
...
var btn = document.getElementById('btnSubmit');
btn.addEventListener('click', function(e) {
e.preventDefault();
var form = $('#fileUploadForm')[0];
var data = new FormData(form);
console.log(data);
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: "/upload",
data: data,
processData: false,
contentType: false,
cache: false,
timeout: 600000,
success: function (data) {
console.log("SUCCESS!");
},
error: function (e) {
console.log("ERROR : ", e);
}
});
});
The code above successfully posts the file to my server. That server has the following:
server.js
app.post('/upload', upload.single('selectedFile'), function(req, res) {
if (req.file) {
console.log('file uploaded');
} else {
console.log('no file');
}
res.send({});
});
Using the code above, "file uploaded" is displayed in the console window as expected. However, I need a more dynamic approach. For that reason, I need to programmatically build the form in JavaScript. In an attempt to do that, I've created the following:
index-2.html
[my UI]
var btn = document.getElementById('btnSubmit');
btn.addEventListener('click', function(e) {
var form = document.createElement('form');
form.action = '/upload';
form.method = 'POST';
form.enctype = 'multipart/form-data';
var node = document.createElement("input");
node.name = 'selectedFile';
node.value = GLOBAL_SELECTED_FILE;
form.appendChild(node);
var data = new FormData(form);
data.append('id', this.id);
console.log(data);
$.ajax({
type: 'POST',
url: '/profile-picture/upload',
enctype: 'multipart/form-data',
data: data,
contentType: false,
processData: false,
success: function(res) {
console.log('success!');
},
error: function(xhr, status, err) {
console.log('error');
}
});
});
This second approach does not work. To clarify, the GLOBAL_SELECTED_FILE variable is the data of a file that was selected from an input element. The data is loaded via the FileReader api. That looks like this:
var GLOBAL_SELECTED_FILE = null;
var fileReader = new FileReader();
fileReader.onload = function(e) {
GLOBAL_SELECTED_FILE = e.target.result;
}
fileReader.readAsDataURL(fileSelected); // file selected comes from the onchange event on a <input type="file">..</input> element
Basically, I'm loading a preview of the image. Anyways, when I hit the submit button in the working version (index-1.html), I notice in Fiddler that a different value is sent over the value sent in index-2.html.
With the approach in index-1.html, Fiddler shows something like this in the "TextView" tab:
------WebKitFormBoundary183mBxXxf1HoE4Et
Content-Disposition: form-data; name="selectedFile"; filename="picture.PNG"
Content-Type: image/png
PNG
However, when I look in the "TextView" tab in Fiddler for the data sent via index-2.html, I see the following:
------WebKitFormBoundary9UHBP02of1OI5Zb6
Content-Disposition: form-data; name="selectedFile"
data:image/png;base64,iVBORw0KGg[A LOT MORE TO GO]
It's like the FormData is using two different encodings for the same value. Yet, I don't understand why. How do I get index-2.html to send the image in the same format as index-1.html so that Multer will populate the req.file property?
Thank you!
In index-1.html, you are using a file input:
<input type="file" id="selectedFile" name="selectedFile" />
In index-2.html, you are creating an ordinary form input (not a file input):
var node = document.createElement("input");
node.name = 'selectedFile';
node.value = GLOBAL_SELECTED_FILE;
form.appendChild(node);
To create a file input, you would need to add node.type = 'file'. However, you won't be able to set the value because browser security restrictions prevent setting the value of file inputs.
Instead, what you need to do is append the file that was selected by the user to the FormData object:
var data = new FormData(form);
data.append('id', this.id);
data.append('selectedFile', $('#fileInputElement')[0].files[0]);

Submit HTML form data as a file / Combine form data + file and send as single file in Javascript

I have a form with input field like some textfields ,textareas,dropdowns and a file upload field which the user will upload while filling the form i want to send form contents (both form field values + uploaded file) as one file to the server below is a very simplified version of my problem .Say i have the following markup
<form id="myForm" method="post" action="something">
<input type="text" name="username" id="username">
<input type="text" name="email" id="email">
<input type="file" name="myFile" id="myFile">
</form>
So now what i want is instead of sending above 2 text fields and a file separately i want them to get embedded in a file and then get sent as a whole.
example
Note that the server where i am sending is third party and only excepts files also file format is proprietary but nonetheless it still a ASCII plain/text.I realize that it's only possible by AJAX and fileReader API so here is what i have tried
var file;
$('#myFile').change(function(e){
file = this.files[0];
var fr = new FileReader();
fr.onload = function(event){
fileData = fr.result;
};
fr.readAsDataURL(file);
$('#myForm').submit(function(e){
e.preventDefault();//prevent submit
var myFile= [$('#username').val(),$('#email').val(),fileData];
$.ajax({
url : "some url",
type: "POST",
contentType:false,
processData:false,
data: myFile;
success:function(data){ }
});
});
Issue is that upon form submission no file gets sent .Any help would be greatly appreciated , thanks.
In form submit you can do as mentioned below for send file with AJAX request
$('#myform').submit(function(e){
e.preventDefault();//prevent submit
var form_data = new FormData();
form_data.append('file', $('#myfile').prop('files')[0]);
form_data.append('username', $("#username").val());
form_data.append('phone', $("#phone").val());
$.ajax({
url : "some url",
type: "POST",
contentType:false,
processData:false,
data: form_data;
success:function(data){ }
});
});
There are 2 parts
Convert file to string format or serialize it on client side using FileReader API
Combine your form values with this string and send them as a file.
Part one
I don't know if you have noticed or not but when you use readAsDataURL() you don't get the original file byte-stream but its base64 encoded version so keeping that in mind change you code to
var fileData;
$('#myFile').change(function(e){
file = this.files[0];
var fr = new FileReader();
fr.onload = function(event) {
encfileData = fr.result;
startInx = encfileData.indexOf('base64');
startInx += 7;
tmp = encfileData.substr(startInx);
//removes the file MIME header part ie. "data:text/plain;base64," before decoding
//regex may be preferable
fileData = atob(tmp); //DECODE
};
fr.readAsDataURL(file);
});
So now you have a string containing your file's byte-stream now as you have said there is some format so depending on that you do whatever manipulation you may need to make it align with the format, since you have mentioned it's plain text format so basic string function are sufficient here.For next part i assume simple colon based CSV format key1:value1,key2:value2
Part Two
Now to truly create a file out of thin air you can use either File or Blob but i would suggest using Blob due to its better support.To contain the file you require FormData simply append your blob to it and send
$('#myForm').submit(function(e){
e.preventDefault();
var txtData = "\n username:"+$("#username").val()+","+"email:"+$("#email").val();
// NOTE: windows uses \r\n instead of \n for newlines
var payLoad = fileData + txtData; //append text field data to the file data
var blob = new Blob([payLoad], {type : 'plain/txt'});
var form = new FormData();
var fileName = 'combined.txt'; //filename that will be used on server
form.append('something', blob, fileName);
$.ajax({
url: "some url",
type: "POST",
cache: false,
contentType: false,
processData: false,
data: form,
success: function(response){alert(response);}
});
});
If using php on linux your $_FILES should look something like this
Array
(
[something] => Array
(
[name] => combined.txt
[type] => plain/txt
[tmp_name] => /tmp/phpJvSJ94
[error] => 0
[size] => 95
)
)
It seems that you're passing sending the wrong variable in your AJAX payload - shouldn't you be sending fileData instead of file?
You can upload data and files:
HTML
<form id="data" method="post" enctype="multipart/form-data">
<input type="text" name="username" id="username">
<input type="text" name="email" id="email">
<input type="file" name="myFile" id="myFile">
</form>
Jquery
$("form#data").submit(function(){
var formData = new FormData($(this)[0]);
$.ajax({
url: 'your_url',
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});

Categories

Resources