Upload Avatar To Server Using AJAX - javascript

I have looked into the best way to do this and keep getting conflicting information and advice on the various demonstrations.
My code is as follows...
html
<img src="http://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50?s=265&d=identicon&r=PG" style="border: thin solid #999999;"/>
<p>Change<span class="pull-right">Powered by Gravatar</span></p>
<input type="file" name="avatar-uploader" id="avatar-uploader" style="display: none;" />
javascript
$('input[type=file]').on('change', function(){
$.ajax({
url: "/ajax/upload-new-avatar.ajax.php", // Url to which the request is send
type: "POST", // Type of request to be send, called as method
data: new FormData(this), // Data sent to server, a set of key/value pairs (i.e. form fields and values)
contentType: false, // The content type used when sending data to the server.
cache: false, // To unable request pages to be cached
processData:false, // To send DOMDocument or non processed data file it is set to false
success: function(data) // A function to be called if request succeeds
{
alert("Success");
}
});
});
PHP: /ajax/upload-new-avatar.ajax.php
error_reporting(E_ALL);
ini_set('display_errors', 1);
session_start();
$sourcePath = $_FILES['avatar-uploader']['tmp_name']; // Storing source path of the file in a variable
$targetPath = "".$_FILES['avatar-uploader']['name']; // Target path where file is to be stored
move_uploaded_file($sourcePath,$targetPath) ; // Moving Uploaded file
I'm sure there is something simple that I am missing here and i'm going to feel pretty stupid afterwards but could someone explain to me why the image isn't being uploaded to the server and saved in the AJAX directory for further processing.
What I need it to do is when the user clicks on the "change" hyperlink below the image it opens a file upload dialog (working), once an image has been selected it automatically uploads to the server over an AJAX connection (possibly working, logging shows the PHP file is being triggered), and then the image file needs to be saved in the AJAX directory to be further processed later in the code for it to be uploaded to the avatar service.
Thanks in advance.

Have managed to get it working...
Here is my amended code...
Javascript
$('input[type=file]').on('change', function(event){
files = event.target.files;
event.stopPropagation(); // Stop stuff happening
event.preventDefault(); // Totally stop stuff happening
$("#avatar-status").text("Loading new avatar...");
$("#avatar").css("opacity", "0.4");
$("#avatar").css("filter", "alpha(opacity=40);");
//Create a formdata object and add the files
var data = new FormData();
$.each(files, function(key, value) {
data.append(key, value);
});
$.ajax({
url: '/ajax/upload-new-avatar.ajax.php?files',
type: 'POST',
data: data,
cache: false,
dataType: 'json',
processData: false, // Don't process the files
contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function(data, textStatus, jqXHR) {
if(typeof data.error === 'undefined') {
//Success so call function to process the form
//submitForm(event, data);
$("#avatar-status").text("Powered by Gravatar");
$("#avatar").css("opacity", "");
$("#avatar").css("filter", "");
} else {
//Handle errors here
alert('ERRORS: ' + textStatus);
}
},
error: function(jqXHR, textStatus, errorThrown) {
//Handle errors here
alert('ERRORS: ' + textStatus);
}
});
});
PHP
session_start();
require_once("../libraries/logging.lib.php");
new LogEntry("AJAX Upload Started - UploadNewAvatar", Log::DEBUG, "AvatarUpload");
sleep(3);
$data = array();
if(isset($_GET['files'])) {
$error = false;
$files = array();
$uploaddir = '../tmp/';
foreach($_FILES as $file) {
if(move_uploaded_file($file['tmp_name'], $uploaddir .basename($file['name']))) {
$files[] = $uploaddir .$file['name'];
new LogEntry("UploadNewAvatar - Upload Successful", Log::DEBUG, "AvatarUpload");
} else {
$error = true;
new LogEntry("UploadNewAvatar - Errors Occured", Log::ERROR, "AvatarUpload");
}
}
$data = ($error) ? array('error' => 'There was an error uploading your files') : array('files' => $files);
} else {
$data = array('success' => 'Form was submitted', 'formData' => $_POST);
new LogEntry("UploadNewAvatar - Form was submitted successfully", Log::DEBUG, "AvatarUpload");
}
echo json_encode($data);
HTML
<img id="avatar" src="http://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50?s=265&d=identicon&r=PG" style="border: thin solid #999999;"/>
<p>Change<span id="avatar-status" class="pull-right">Powered by Gravatar</span></p>
<input type="file" name="upfile" id="upfile" style="display: none;" />

Related

Displaying each data line by line during AJAX CSV File Upload

I am using papaparse, Jquery AJAX, PHP and have successfully finished the parsing of csv, However, I would like to display data while my CSV file is being uploaded.
Here is a bit of my code;
var xhr_file = null;
$('#fileVariants').change(function(e){
var file = e.target.files[0];
splitFileName = file['name'].split(".");
fileType = splitFileName.slice(-1)[0];
if(fileType != 'csv')
{
$('.error-message').html('<br /><div class="notification is-warning">Only CSV file extension is allowed!</div><br />');
}
else
{
Papa.parse(file, {
header: false,
dynamicTyping: true,
skipEmptyLines: true,
complete: function(results, file) {
file_arr = results.data;
file_chunk = results.data;
$('#uploadVariantsBtn').attr('disabled', false);
}// End complete: function(results, file)
});
}
});
$(function(){
$('#uploadVariants').submit(function(e){
if($('#fileVariants').val() == '')
{
$('.error-message').html('<div class="alert alert-danger" role="alert">File is required!</div><br />');
return false;
}
var method = $(this).attr('method');
var url = $(this).attr('action');
var parameters = 'row=' + JSON.stringify(file_chunk);
xhr_file = $.ajax({
type : method,
url : url,
data : parameters,
cache : false,
async: false,
dataType : "script",
beforeSend: function(xhr){
$('#uploadVariantsBtn').attr('disabled', true);
$('.error-message').html('<br /><div class="notification is-info has-text-centered"><img width="110" src="{{ asset("img/loading.gif") }}" title="Uploading" /></div>');
$('.error-message').show();
if (xhr_file != null)
{
xhr_file.abort();
}
}
}).complete(function(data){
$('#uploadVariantsBtn').attr('disabled', false);
$('.error-message').html('<div class="alert alert-success" role="alert">Product Variants has been updated!</div><br />');
// $('.show-results').html('<h3>Product Variants have been updated!</h3>');
}).fail(function(jqXHR, textStatus){
console.log('Request failed: ' + textStatus);
});
return false;
e.preventDefault();
});
});
So instead of showing a progress bar in the upload, I would like to display each data line by line to show the progress.
For Example :
Product Data 1 has been successfully updated!
Product Data 2 has been successfully updated!
Product Data 3 already exist!
Product Data 4 has been successfully updated!
Product Data 5 has been successfully updated!
Is there any way to do that using PHP, Javascript, AJAX?
You uploaded all of your data at once, then the server process your data, in completion it returns the result. You actually want the long running process's status of every single row process data.
For that, you actually need a seperate php file and ajax call. Your original php file should update the status in session or db, like below,
session_start();
$_SESSION['status'] = $status;
session_write_close();
Note that, this piece of code should be inside the loop of processing data. You should start() and close() this particular session because same session cannot be opened in other process, as we need to access this session from 2nd php file which looks like below,
ob_start();
session_start();
session_write_close();
$output = array();
$output['status'] = $_SESSION['status'];
echo json_encode($output);
Now the server side code is okay, you need to query the 2nd php with regular interval to get the processing status,
var timeout = setInterval('showUpdate()', 1000);
function showUpdate(){
$.get( "2ndPhp.php", function( data ) {
var returnData = data.status;
if (returnData.length>0){
// This is server returned update data, you can show this or convert it to
//progressbar
}
}, "json");
}
When you main process ends, you can close this loop by closing this interval.
.complete(function(data){
clearInterval(timeout);
$('#uploadVariantsBtn').attr('disabled', false);
$('.error-message').html('<div class="alert alert-success" role="alert">Product
Variants has been updated!</div><br />');
// $('.show-results').html('<h3>Product Variants have been updated!</h3>');
}).fail(function(jqXHR, textStatus){
console.log('Request failed: ' + textStatus);
});

File upload not working in PHP , $_POST['file'] , not able to extract file

I have the following HTML code:
<form action="mail/filesend.php" method="POST" accept-charset="utf-8" enctype="multipart/form-data" validate>
<div class="input-wrpr">
<input type="file" name="files[]">
</div>
<button type="submit">
Send File
</button>
</form>
And then the following file upload code in jQuery:
$(function () {
let files = null;
$('input[type="file"]').on('change' , (e) => {
files = e.target.files;
});
$('form').submit(function(e){
e.stopPropagation();
e.preventDefault();
let data = new FormData();
// files = $('input[type="file"]')[0].files;
$.each(files, function(key, value){
data.append(key, value);
});
console.log(data.getAll('0'));
// console.log(data);
$.ajax({
type: $(this).attr('method'),
url : $(this).attr('action'),
data: data,
cache: false,
dataType: 'json',
processData: false, // Don't process the files
contentType: false, // Set content type to false as jQuery will tell the server its a query string request
data : data
}).done(function(data){
// console.log(data);
if (! data.success) {
// console.log(data.errors);
/*for(let er in data.errors) {
console.log(data.errors[er])
}*/
console.log(data);
} else {
/* else condition fires if form submission is successful ! */
console.log(data.file);
}
}).fail(function(data){
console.log(data);
});
});
});
And the following PHP code for testing :
<?php
// You need to add server side validation and better error handling here
$data = array();
if(isset($_FILES['files'])) {
$data = array('file' => 'I a in if');
}
else {
$data = array('file' => 'I am in else');
}
echo json_encode($data);
?>
Now when i check my console i see that the PHP if condition is not passing , that is it is unable to detect:
isset($_POST['files'])
Why is this happening ? I have tried using isset($_FILES['files']), also I have tried renaming my html file input field to just files instead of files[] , but this does't seem to work , What am I doing wrong ?
I was following the tutorial HERE. But somehow the example I have created just does't work.
Try to print_r($_FILES) and check if it shows an array of file,
If it does, use the same key in $_FILES['same_key_here'] and it supposed to work,
Let me know if it doesn't
If you want to send files, do something like this.
This may help you.
var fileInput = $("#upload_img")[0]; // id of your file
var formData = new FormData();
formData.append("image_file",fileInput.files[0]); //'xmlfile' will be your key
Check in your php code like,
echo $_POST['image_file'];

How do I send images in an ajax request? [duplicate]

I want to implement a simple file upload in my intranet-page, with the smallest setup possible.
This is my HTML part:
<input id="sortpicture" type="file" name="sortpic" />
<button id="upload">Upload</button>
and this is my JS jquery script:
$("#upload").on("click", function() {
var file_data = $("#sortpicture").prop("files")[0];
var form_data = new FormData();
form_data.append("file", file_data);
alert(form_data);
$.ajax({
url: "/uploads",
dataType: 'script',
cache: false,
contentType: false,
processData: false,
data: form_data,
type: 'post',
success: function(){
alert("works");
}
});
});
There is a folder named "uploads" in the root directory of the website, with change permissions for "users" and "IIS_users".
When I select a file with the file-form and press the upload button, the first alert returns "[object FormData]". the second alert doesn't get called and the"uploads" folder is empty too!?
Can someone help my finding out whats wrong?
Also the next step should be, to rename the file with a server side generated name. Maybe someone can give me a solution for this, too.
You need a script that runs on the server to move the file to the uploads directory. The jQuery ajax method (running on the client in the browser) sends the form data to the server, then a script running on the server handles the upload.
Your HTML is fine, but update your JS jQuery script to look like this:
(Look for comments after // <-- )
$('#upload').on('click', function() {
var file_data = $('#sortpicture').prop('files')[0];
var form_data = new FormData();
form_data.append('file', file_data);
alert(form_data);
$.ajax({
url: 'upload.php', // <-- point to server-side PHP script
dataType: 'text', // <-- what to expect back from the PHP script, if anything
cache: false,
contentType: false,
processData: false,
data: form_data,
type: 'post',
success: function(php_script_response){
alert(php_script_response); // <-- display response from the PHP script, if any
}
});
});
And now for the server-side script, using PHP in this case.
upload.php: a PHP script that is located and runs on the server, and directs the file to the uploads directory:
<?php
if ( 0 < $_FILES['file']['error'] ) {
echo 'Error: ' . $_FILES['file']['error'] . '<br>';
}
else {
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $_FILES['file']['name']);
}
?>
Also, a couple things about the destination directory:
Make sure you have the correct server path, i.e., starting at the PHP script location what is the path to the uploads directory, and
Make sure it's writeable.
And a little bit about the PHP function move_uploaded_file, used in the upload.php script:
move_uploaded_file(
// this is where the file is temporarily stored on the server when uploaded
// do not change this
$_FILES['file']['tmp_name'],
// this is where you want to put the file and what you want to name it
// in this case we are putting in a directory called "uploads"
// and giving it the original filename
'uploads/' . $_FILES['file']['name']
);
$_FILES['file']['name'] is the name of the file as it is uploaded. You don't have to use that. You can give the file any name (server filesystem compatible) you want:
move_uploaded_file(
$_FILES['file']['tmp_name'],
'uploads/my_new_filename.whatever'
);
And finally, be aware of your PHP upload_max_filesize AND post_max_size configuration values, and be sure your test files do not exceed either. Here's some help how you check PHP configuration and how you set max filesize and post settings.
**1. index.php**
<body>
<span id="msg" style="color:red"></span><br/>
<input type="file" id="photo"><br/>
<script type="text/javascript" src="jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(document).on('change','#photo',function(){
var property = document.getElementById('photo').files[0];
var image_name = property.name;
var image_extension = image_name.split('.').pop().toLowerCase();
if(jQuery.inArray(image_extension,['gif','jpg','jpeg','']) == -1){
alert("Invalid image file");
}
var form_data = new FormData();
form_data.append("file",property);
$.ajax({
url:'upload.php',
method:'POST',
data:form_data,
contentType:false,
cache:false,
processData:false,
beforeSend:function(){
$('#msg').html('Loading......');
},
success:function(data){
console.log(data);
$('#msg').html(data);
}
});
});
});
</script>
</body>
**2.upload.php**
<?php
if($_FILES['file']['name'] != ''){
$test = explode('.', $_FILES['file']['name']);
$extension = end($test);
$name = rand(100,999).'.'.$extension;
$location = 'uploads/'.$name;
move_uploaded_file($_FILES['file']['tmp_name'], $location);
echo '<img src="'.$location.'" height="100" width="100" />';
}
Use pure js
async function saveFile()
{
let formData = new FormData();
formData.append("file", sortpicture.files[0]);
await fetch('/uploads', {method: "POST", body: formData});
alert('works');
}
<input id="sortpicture" type="file" name="sortpic" />
<button id="upload" onclick="saveFile()">Upload</button>
<br>Before click upload look on chrome>console>network (in this snipped we will see 404)
The filename is automatically included to request and server can read it, the 'content-type' is automatically set to 'multipart/form-data'. Here is more developed example with error handling and additional json sending
async function saveFile(inp)
{
let user = { name:'john', age:34 };
let formData = new FormData();
let photo = inp.files[0];
formData.append("photo", photo);
formData.append("user", JSON.stringify(user));
try {
let r = await fetch('/upload/image', {method: "POST", body: formData});
console.log('HTTP response code:',r.status);
alert('success');
} catch(e) {
console.log('Huston we have problem...:', e);
}
}
<input type="file" onchange="saveFile(this)" >
<br><br>
Before selecting the file Open chrome console > network tab to see the request details.
<br><br>
<small>Because in this example we send request to https://stacksnippets.net/upload/image the response code will be 404 ofcourse...</small>
var formData = new FormData($("#YOUR_FORM_ID")[0]);
$.ajax({
url: "upload.php",
type: "POST",
data : formData,
processData: false,
contentType: false,
beforeSend: function() {
},
success: function(data){
},
error: function(xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
and this is the php file to receive the uplaoded files
<?
$data = array();
//check with your logic
if (isset($_FILES)) {
$error = false;
$files = array();
$uploaddir = $target_dir;
foreach ($_FILES as $file) {
if (move_uploaded_file($file['tmp_name'], $uploaddir . basename( $file['name']))) {
$files[] = $uploaddir . $file['name'];
} else {
$error = true;
}
}
$data = ($error) ? array('error' => 'There was an error uploading your files') : array('files' => $files);
} else {
$data = array('success' => 'NO FILES ARE SENT','formData' => $_REQUEST);
}
echo json_encode($data);
?>

Having a bit of trouble with my AJAX POST request to my PHP file

I'm trying to provide data to my MYSQL Database using Ajax, however, for some reason my PHP file is not reading the JSON array that I post to the file. Within the array I also have a file to store an image on my server as well as my database.
Javascript file
$(document).ready(function(){
// Give Data to PHP
// process the form
$('form').submit(function(event) {
// get the form data
// there are many ways to get this data using jQuery (you can use the class or id also)
//formData.append('tax_file', $('input[type=file]')[0].files[0]
var img = $('input[name=img]').prop('files')[0];
var name = img.name,
tmp = img.tmp_name,
size = img.size,
form = $('input[name=form-submit]').val(),
myName = $('input[name=my-name]').val(),
desc = $('input[name=description]').val();
// document.write(name + tmp + size);
var formData = {
'form-submit' : form,
'my-name' : myName,
'description' : desc,
'img' : name,
'tmp_name' : tmp,
'size' : size
};
// document.write(JSON.stringify(formData));
console.log(formData);
// process the form
$.ajax({
url : 'insert-bio.php', // the url where we want to POST
type : 'POST', // define the type of HTTP verb we want to use (POST for our form)
data : formData, // our data object
processData : false,
contentType : false,
dataType : 'json', // what type of data do we expect back from the server
encode : true
})
// using the done promise callback
.done(function(data) {
// log data to the console so we can see
console.log(data);
// here we will handle errors and validation messages
});
// stop the form from submitting the normal way and refreshing the page
event.preventDefault();
});
});
My PHP file
include('../db.php');
$conn = new Database();
echo explode(",", $_POST['data']);
if(isset($_POST['form-submit'])){
// text data
$name = strip_tags($_POST['my-name']);
$desc = strip_tags($_POST['description']);
// picture stuff
$file = rand(1000,100000)."-".$_FILES['img']['name'];
$file_loc = $_FILES['img']['tmp_name'];
$file_size = $_FILES['img']['size'];
$file_type = $_FILES['img']['type'];
// folder for profile pic
$folder = "bio-pic/";
// new file size in KB
$new_size = $file_size/1024;
// make file name in lower case
$new_file_name = strtolower($file);
// final pic file
$final_file=str_replace(' ','-',$new_file_name);
// mysql query for form data
if(move_uploaded_file($file_loc,$folder.$final_file)){
$sql="INSERT INTO bio(img, name, description) VALUES('$final_file', '$name', '$desc')";
$conn->query($sql);
}
} else {
echo "Need data";
}
$query = $conn->query("SELECT * FROM bio");
$results=$query->fetchAll(PDO::FETCH_ASSOC);
$parse_bio_json = json_encode($results);
file_put_contents('bio-DATA.json', $parse_bio_json);
echo $parse_bio_json;
The console shows that I have made contact with my PHP file, but it simply has not read any data.
The error on the PHP file:
Notice: Undefined index: data in /Applications/XAMPP/xamppfiles/htdocs/WEBSITE/BIO/insert-bio.php on line 8
Notice: Array to string conversion in /Applications/XAMPP/xamppfiles/htdocs/WEBSITE/BIO/insert-bio.php on line 8 ArrayNeed data[]
I had the same issue back in the day. After doing lots of research I found out that JSON cannot have a property that holds a file value. However, you can follow this example. It worked great for me. Hope it helps :)
$('#upload').on('click', function() {
var file_data = $('#sortpicture').prop('files')[0];
var form_data = new FormData();
form_data.append('file', file_data);
alert(form_data);
$.ajax({
url: 'upload.php', // point to server-side PHP script
dataType: 'text', // what to expect back from the PHP script, if anything
cache: false,
contentType: false,
processData: false,
data: form_data,
type: 'post',
success: function(php_script_response){
alert(php_script_response); // display response from the PHP script, if any
}
});
});
PHP
<?php
if ( 0 < $_FILES['file']['error'] ) {
echo 'Error: ' . $_FILES['file']['error'] . '<br>';
}
else {
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $_FILES['file']['name']);
}
?>
Credit goes to -> jQuery AJAX file upload PHP

jQuery-File-Upload inconsistently gives file data

jQuery-File-Upload
Upload script:
$('#fileupload').fileupload({
url: 'api/combox_upload.php',
type: 'POST',
dataType: 'json',
dropZone: $dropZone,
singleFileUploads: true,
done: function (e, data) {
attachments = attachments.concat(data.result);
refreshAttachments();
},
add: function(e, data) {
var file = data.files[0];
data.context =
$('<li>',{'class':'file-upload-item'})
.append($('<span>').text(file.name))
.append(
$('<div>',{'class':'progressbar'})
.append($('<div>',{'class':'progress'}))
).appendTo($fileUploads);
data.submit(); // start upload immediately
},
progress: function(e, data) {
var progress = data.loaded / data.total;
data.context.find('.progress').stop().animate({'width':(progress*100)+'%'},100,'linear');
//data.context.find('.progress').css({'width':(progress*100)+'%'});
}
});
In my api/combox_upload.php script I echo json_encode($_FILES) and half the time it comes back blank (I'm watching the XHR request responses in Chrome developer toolbar).
Why is that? How do I fix it so it always submits the file?
Edit: It seems to happen more frequently with larger files.
Could it be an issue with PHP not handling multipart data correctly? I noticed the XHR request comes in immediately, as soon as the file upload begins, but PHP obviously hasn't gotten the whole file yet... so what does it do? Does it block when I try to access the $_FILES object or does it just give me an empty array? Do I have to something special?
Through trial and error I discovered that this problem only occurs with files larger than about 23 MiB. I'm not sure if that's a universal constant or specific to how my server is configured.
Nevertheless, I figured out how to get around this limitation. You need to set singleFileUploads to true and multipart to false, e.g.
$('#fileupload').fileupload({
url: 'api/upload.php',
type: 'POST',
dataType: 'json',
singleFileUploads: true,
multipart: false,
...
And then in your php script you can read in the data like this:
$handle = fopen('php://input', 'r');
$file_data = '';
while(($buffer = fgets($handle, 4096)) !== false) {
$file_data .= $buffer;
}
fclose($handle);
The $_FILES array will still be empty, so you can't get the filename out of there, but it seems to be set in the Content-Disposition header. I wrote a regex to pull it out:
$headers = getallheaders();
$filesize = strlen($file_data);
if(isset($headers['Content-Disposition']) && preg_match('`\bfilename="((?:\\.|[^"])*)"`',$headers['Content-Disposition'], $m)) {
$filename = urldecode($m[1]);
} else {
$filename = 'unknown';
}

Categories