Loop through $_FILES causes JSON unexpected Token - php

***** Update:** The issue I believe is with the dSubmit function, it might not be handling multipart form data therefore causes PHP to throw an error when the foreach is executed? I've submitted over arrays through the function without issue, is there something different with the files[]
I have a AJAX form submission on a website, the JSON array that is returned is used to show message or direct to another page. Everything works well until I loop through file uploads sent through the form via the PHP script. I have removed all possible extra code so it is now bare bones and I still can't resolve it:
upload.php
<?php
foreach($_FILES['files']['name'] as $f => $name){};
$returnData = array(
"infoMsg" => "message for user",
"color" => "orange"
);
echo json_encode($returnData);
?>
html snippet:
<form id="fileUpload" name="fileUpload" enctype="multipart/form-data">
<input type="file" id="file" name="files[]" multiple="multiple"/>
</form>
<button onclick="dSubmit('fileUpload' , 'inc/upload.php')">test</button>
dSubmit is the function to submit the form, everything is working as expected until I introduce the looping of the uploaded files. The error I receive is:
Uncaught SyntaxError: Unexpected token < in JSON at position 0
I can see no extra characters/whitespace or anything else that might cause the JSON issue.
Here's the dSubmit code found in the head:
function dSubmit(formName, formAction){
// formName = id of Form to process
// formAction = php file to parse data to
var url = formAction;
event.preventDefault()
for ( instance in CKEDITOR.instances )
CKEDITOR.instances[instance].updateElement();
$.ajax({
type: "POST",
url: url,
data: $("#" + formName).serialize(),
success: function(returnData)
{
var data = JSON.parse(returnData); // Return php array from formAction
var passedInfoMsg = (data['infoMsg']); // infoMsg (if set)
var color = (data['color']); // infoMsg color (if set)
var resetForm = (data['reset']); // boolean reset submitted form upon submission
var fileToLoad = (data['fileToLoad']); // fileToLoad (if set)
var divToLoad = (data['divToLoad']); // divToLoad fileToLoad in (if set)
console.log("Form Return: passedInfoMsg: " + passedInfoMsg + " | color: " + color + " | Reset: " + resetForm + " | fileToLoad: " + fileToLoad + " | divToLoad: " + divToLoad);
if(passedInfoMsg!==undefined) {
// If message defined, display message
infoMsg(passedInfoMsg,color);
}
if(resetForm===true) {
// clear submitted form upon request from formAction
clearForm($("#"+formName))
}
if(fileToLoad!==undefined) {
// if fileToLoad is set, run dLoader
dLoader(fileToLoad,divToLoad);
}
}
});
return false; // avoid to execute the actual submit of the form.
}
The full code as requested:
storage.php ( where uploads take place ):
<?php
require $_SERVER['DOCUMENT_ROOT'] . '/../vendor/bucketScripts/start.php'; // include AWS email parser
$folderTitle = "Client Portal";
$projectId = "36";
$folder = "client";
$objects = $s3->getIterator('ListObjects', array(
"Bucket" => "openplanman",
"Prefix" => "Projects/$projectId/$folder/" //must have the trailing forward slash "/"
));
$passedPrefix = "Projects/$projectId/$folder/";
?>
<div class="row">
<div class="12u 12u$(medium)">
<h3><?php echo $folderTitle;?></h3>
</div>
<form id="fileUpload" name="fileUpload" enctype="multipart/form-data" method="POST" action="inc/uploadFiles.php" target="_blank">
<input type="hidden" name="projectId" value="<?php echo $projectId;?>">
<input type="hidden" name="uploadFolder" value="<?php echo $folder;?>">
<input type="hidden" name="folderTitle" value="<?php echo $folderTitle;?>">
<input type="file" id="file" name="files[]" multiple="multiple"/>
<input type="submit" value="Upload">
</form>
<button onclick="dSubmit('fileUpload' , 'inc/uploadFiles.php')">test</button>
<div class="12u 12u$(medium)">
<table>
<?php
$fileArray = array();
foreach ($objects as $object) {
// Load into a new array
array_push($fileArray, $object['Key']);
}
foreach ($fileArray as $file) {
$noPrefixFileName = str_replace("$passedPrefix","",$file);
if($noPrefixFileName!=null)
{
$urlFilename = urlencode($noPrefixFileName);
echo "<tr><td>" . $noPrefixFileName . "</td><td><a onclick=\"fileRequest.php?id=$projectId&folder=$folder&req=$urlFilename\" target='_blank'><i class='fa fa-cloud-download' aria-hidden='true'></a></td><td><i class='fa fa-eye' aria-hidden='true'></td></tr>";
}
}
?>
</table>
</div>
</div>
uploadFiles.php (PHP script that handles the upload, works when POST not through AJAX)
<?php
require $_SERVER['DOCUMENT_ROOT'] . '/../vendor/bucketScripts/start.php';
$err = 0;
$projectId = $_POST['projectId'];
$uploadFolder = $_POST['uploadFolder'];
$path = $_SERVER['DOCUMENT_ROOT'] . '/../tmp/'; // include AWS email parser
$bucketPath = "../../../tmp/";
if(isset($_POST) and $_SERVER['REQUEST_METHOD'] == "POST"){
// Loop $_FILES to exeicute all files
foreach ($_FILES['files']['name'] as $f => $name) {
if ($_FILES['files']['error'][$f] == 4) {
continue; // Skip file if any error found
}
if ($_FILES['files']['error'][$f] == 0) {
// No error found! Move uploaded files
if(move_uploaded_file($_FILES["files"]["tmp_name"][$f], $path.$name))
$fileName = $_FILES["files"]["name"][$f];
// echo "<br>Key: " . "Projects/$projectId/$uploadFolder/$fileName";
// echo "<br>Source: " . "$bucketPath$fileName";
try {
$s3->putObject([
'Bucket' => $config['s3']['bucket'],
'Key' => "Projects/$projectId/$uploadFolder/$fileName",
'SourceFile' => "$bucketPath$fileName",
'ACL' => 'public-read',
]);
} catch (S3Exception $e) {
$err = 1;
}
unlink($path.$name); // Housekeeping
}
}
}
$returnData = array(
"infoMsg" => "user message",
"color" => "orange",
);
echo json_encode($returnData);
?>

you got this error because there is a PHP error response that treated by the browser as json content and it's not.
you can find out that error response through the chrome developer tools
press F12 to open the developer tools
select Network tab
select XHR filter
select the request that you make
on the right side you can find the response tab which will content the raw response
by the way i think your problem is your code try to iterate through $_FILES['files']['name'] which is string :)

Hope It's helpful..!
Your files array becomes like:-
$_FILES['files'][0]['name']
$_FILES['files'][1]['name']
When you do multiple file upload.

Related

simple parse error with my form submit using ajax and file upload

I'm able to get the file uploaded and in to the directory I want so that part seems to work but I'm not sure why I'm getting a parse error in the js console in chrome. Because of this error my bottom javascript won't execute and I need it to do so.
Here's the ajax:
var files;
// Add events
$('input[type=file]').on('change', prepareUpload);
// Grab the files and set them to our variable
function prepareUpload(event)
{
files = event.target.files;
}
$('form').on('submit', uploadFiles);
// Catch the form submit and upload the files
function uploadFiles(event)
{
event.stopPropagation(); // Stop stuff happening
event.preventDefault(); // Totally stop stuff happening
// START A LOADING SPINNER HERE
// Create a formdata object and add the files
var data = new FormData();
$.each(files, function(key, value)
{
data.append(key, value);
});
$.ajax({
url: 'submit.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)
{
alert(data);
script = $(data).text();
$.globalEval(script);
if(typeof data.error === 'undefined')
{
// Success so call function to process the form
submitForm(event, data);
}
else
{
// Handle errors here
console.log('ERRORS: ' + data.error);
}
},
error: function(jqXHR, textStatus, errorThrown)
{
// Handle errors here
console.log('ERRORS: ' + textStatus);
// STOP LOADING SPINNER
}
});
}
Here's the html:
<?php
echo '<span class="new_profile_save_upload_image_span"><img src="'.$url_root.'/images/615721406-612x612.jpg"/ class="new_profile_save_upload_image_img"></span>';
?>
<form action="" method="post" enctype="multipart/form-data" name="new_profile_save_upload_image_input_form" id="new_profile_save_upload_image_input_form">
<input type="file" id="new_profile_save_upload_image_input" name="new_profile_save_upload_image_input" multiple="" accept="image/x-png,image/gif,image/jpeg"/>
<input type="submit" value="Upload Image" name="submit">
</form>
And here is the php:
<?php
// get mysqli db connection string
$mysqli = new mysqli("localhost", "psych_admin", "asd123", "psych");
if($mysqli->connect_error){
exit('Error db');
}
// Get theme settings and theme colours and assign the theme colour to the
theme name
$stmt = $mysqli->prepare("SELECT name FROM user_profiles WHERE rowid=(SELECT
MAX(rowid) FROM user_profiles);");
$stmt->execute();
$result = $stmt->get_result();
while($row_1 = $result->fetch_assoc())
{
$arr_1[] = $row_1;
}
foreach($arr_1 as $arrs_1)
{
$username = $arrs_1['name'];
}
$data = array();
if(isset($_GET['files']))
{
$error = false;
$files = array();
// Make dir for file uploads to be held
if (!file_exists(''.dirname(__FILE__) . '/content/profiles/'.$username.'/avatar'))
{
mkdir(''.dirname(__FILE__) . '/content/profiles/'.$username.'/avatar', 0777, true);
}
$uploaddir = './content/profiles/'.$username.'/avatar/';
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' => 'Form was submitted', 'formData' => $_POST);
}
echo json_encode($data);
?>
<script>
var scope1 = '<?php echo $url_root;?>';
var scope2 = '<?php echo $username;?>';
var scope3 = '<?php echo $file['name'];?>';
var new_profile_save_upload_image_span_data = '<img src="' + scope1 + '/content/profiles/' + scope2 + '/avatar/' + scope3 + '" class="new_profile_save_upload_image_img">';
$('.new_profile_save_upload_image_span').empty();
$('.new_profile_save_upload_image_span').append(new_profile_save_upload_image_span_data);
</script>
alert(data) doesn't seem to be popping up, so there's something wrong previous to that execution.
I tried this code with simply 'submit.php' but it doesn't seem to work without the 'files' addition to it.
Also do I have the filename correct? Should the file's filename be $file['name'] in php? I'm trying to get the file name as a string and place it in when the default image is (as an image to be displayed), using an img html tag and inserting it via jquery, as you can see at the bottom under .
The ajax should execute this script at the bottom but it doesn't due to the error.
Also is there a nicer way of writing the bottom jquery scripts that I have written?
Error I'm getting:
ERRORS: Syntax Error: Unexpected Token < in JSON at position 103
Thanks in advance.
If you want to return JSON and HTML at the same time, you could put the HTML into an element of the $data array.
<?php
// get mysqli db connection string
$mysqli = new mysqli("localhost", "psych_admin", "asd123", "psych");
if($mysqli->connect_error){
exit('Error db');
}
// Get theme settings and theme colours and assign the theme colour to the
theme name
$stmt = $mysqli->prepare("SELECT name FROM user_profiles WHERE rowid=(SELECT
MAX(rowid) FROM user_profiles);");
$stmt->execute();
$result = $stmt->get_result();
while($row_1 = $result->fetch_assoc())
{
$arr_1[] = $row_1;
}
foreach($arr_1 as $arrs_1)
{
$username = $arrs_1['name'];
}
$data = array();
if(isset($_GET['files']))
{
$error = false;
$files = array();
// Make dir for file uploads to be held
if (!file_exists(''.dirname(__FILE__) . '/content/profiles/'.$username.'/avatar'))
{
mkdir(''.dirname(__FILE__) . '/content/profiles/'.$username.'/avatar', 0777, true);
}
$uploaddir = './content/profiles/'.$username.'/avatar/';
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' => 'Form was submitted', 'formData' => $_POST);
$data['html'] = <<<EOS
<script>
var scope1 = '$url_root';
var scope2 = '$username';
var scope3 = '{$file['name']}';
var new_profile_save_upload_image_span_data = '<img src="' + scope1 + '/content/profiles/' + scope2 + '/avatar/' + scope3 + '" class="new_profile_save_upload_image_img">';
\$('.new_profile_save_upload_image_span').empty();
\$('.new_profile_save_upload_image_span').append(new_profile_save_upload_image_span_data);
</script>
EOS;
}
echo json_encode($data);
?>
Then in the JavaScript you do:
script = $(data.html).text();
It's better to use try-catch block in your PHP code, and send status with the response set to true or false. Also, send the $url_root and $username variables within the JSON object.
See this beginner's guide on Image Uploading with PHP and AJAX to learn everything about creating AJAX handler, validating, saving and sending a response back to the client side.

Obtain AJAX returned object in PHP

I have a program which is running server script on raspberry pi (client which is also a server). I'm scanning a barcode which then executes few commands (including generating XML file). When I submit the form with the 'serial' number, I want to be able to retrieve the filename (string) returned from AJAX ($_POST) method in server.php? if (isset($_POST['filename']) does not return the filename, how do I obtain filename with a single AJAX? and use it in PHP? I have no error messages, the $_POST['filename'] is empty. I tried separating the script into a different file and creating another AJAX calling that PHP script but it did not fully work and I wonder if there is a possibility to do it with a single AJAX and make PHP listen for the returned filename.
Or maybe is there a better way to obtain the filename of the external file than through client-side? (there is always single XML file waiting to be picked up).
server.php
<?php
$show_error = "";
if (isset($_POST['serial'])) {
$serialnumber = $_POST['serial'];
if ($serialnumber > 0) {
if (isset($_POST['filename'])) {
$filenamer = $_POST['filename'];
echo $filenamer;
} else {
echo "no filename returned from ajax call";
}
$remote_file_url = 'http://' . $_SERVER['REMOTE_ADDR'] . '/345.xml'; //FILENAME NEEDED
$local_file = '345.xml'; //FILENAME NEEDED
$copy = copy( $remote_file_url, $local_file );
}
?>
<html>
<body>
<form name="test" method="post">
<input type="number" name="serial" id="serial" value="1">
<input type="submit" name="">
</form>
</body>
<script type="text/javascript">
function scan(serialnumber)
{
return $.ajax({
url : 'http://localhost/test.php',
type : 'POST',
dataType : 'json',
data : { serial_no : serialnumber},
cache : false,
success : function(data) {
var filename = data[Object.keys(data)[1]];
console.log(filename);
}
});
};
scan(<?php echo $serialnumber; ?>);
</script>
</html>
test.php
<?php
header('Access-Control-Allow-Origin: *');
header('Content-type: text/json');
# Get the serial
$serial_no = $_POST['serial_no'];
$return['serial_no'] = $serial_no;
# Get the filename of the XML file
$filename = shell_exec('find /var/www/html/*.xml -printf "%f"');
$return['filename'] = $filename;
$return['scanpink'] = 1;
echo json_encode($return);
?>
As I mentioned in my comment, you don't have filename in php because your form does not include filename field. After receiveing filename from ajax you can do another ajax request with serial & filename fields or the second solution is to use a hidden field. After receiving data in ajax you cannot use them in php - You have to send it (filename) to php.

how to store and send $_FILES via javascript/php

I'm trying to set up a form that can upload to both YouTube and Vimeo simultaneously. I would prefer to use Posterous.com for something like this, but since they've been acquired by twitter, their help team has dropped off the face of the earth as my emails are now going unanswered (they've removed a bunch of services)...
So anyways here's how the youtube process is supposed to work:
Set a title and category for the video you want to upload via webform
submit form, get an access token back from youtube
another form is generated, allowing you to select the file to upload
submit form, access token and file are sent and youtube uploads the video
What I'm trying to do is turn this into a single step with a drag and drop uploader:
drag and drop file onto page
javascript grabs the file information, sets the filename as the video title and uses a default category
javascript calls php and sends filename & category to youtube, gets access token back and creates form with file input
after getting the token, send a POST (via PHP) request with file upload stored in a session variable (right now I have to select the file again and click submit)
shouldn't I be able to use the file information from the first step, store it in a session variable and programmatically submit the token and file information via php? I don't know how to send this data like it was sent as a form submission and I'm not always getting response codes back from youtube to fix my code.
this may be the answer I need: sending xml and headers via curl but I don't know how to set the $xmlString or $videoData
EDIT::
I think I need to do this via PHP, not javascript because I'm trying to modify the following code:
/**
* Create upload form by sending the incoming video meta-data to youtube and
* retrieving a new entry. Prints form HTML to page.
*
* #param string $VideoTitle The title for the video entry.
* #param string $VideoDescription The description for the video entry.
* #param string $VideoCategory The category for the video entry.
* #param string $nextUrl (optional) The URL to redirect back to after form upload has completed.
* #return void
*/
function createUploadForm($videoTitle, $videoCategory, $nextUrl = null) {
$httpClient = getAuthSubHttpClient();
$youTubeService = new Zend_Gdata_YouTube($httpClient);
$newVideoEntry = new Zend_Gdata_YouTube_VideoEntry();
$newVideoEntry->setVideoTitle($videoTitle);
//make sure first character in category is capitalized
$videoCategory = strtoupper(substr($videoCategory, 0, 1))
. substr($videoCategory, 1);
$newVideoEntry->setVideoCategory($videoCategory);
// convert videoTags from whitespace separated into comma separated
$tokenHandlerUrl = 'https://gdata.youtube.com/action/GetUploadToken';
try {
$tokenArray = $youTubeService->getFormUploadToken($newVideoEntry, $tokenHandlerUrl);
if (loggingEnabled()) {
logMessage($httpClient->getLastRequest(), 'request');
logMessage($httpClient->getLastResponse()->getBody(), 'response');
}
} catch (Zend_Gdata_App_HttpException $httpException) {
print 'ERROR ' . $httpException->getMessage()
. ' HTTP details<br /><textarea cols="100" rows="20">'
. $httpException->getRawResponseBody()
. '</textarea><br />'
. '<a href="session_details.php">'
. 'click here to view details of last request</a><br />';
return;
} catch (Zend_Gdata_App_Exception $e) {
print 'ERROR - Could not retrieve token for syndicated upload. '
. $e->getMessage()
. '<br /><a href="session_details.php">'
. 'click here to view details of last request</a><br />';
return;
}
$tokenValue = $tokenArray['token'];
$postUrl = $tokenArray['url'];
// place to redirect user after upload
if (!$nextUrl) {
$nextUrl = $_SESSION['homeUrl'];
}
//instead of echoing the form below, send $_FILES from previous form submit
print <<< END
<br />
<form id="uploadToYouTubeForm" action="${postUrl}?nexturl=${nextUrl}" method="post" enctype="multipart/form-data">
<input id="uploadToYouTube" name="file" type="file" />
<input name="token" type="hidden" value="${tokenValue}"/>
<input value="Upload Video File" type="submit" />
</form>
END;
}
I think I may have a solution. Below is the form I want to use:
<!--removing the action ensures form will be sent via javascript, then when that request comes back, I can add in the authenticated youtube URL needed-->
<form id="upload" action="" method="POST" enctype="multipart/form-data" class="form-horizontal"><!--upload.php-->
<fieldset>
<legend><h1>Video File Upload</h1></legend>
<input type="hidden" id="MAX_FILE_SIZE" name="MAX_FILE_SIZE" value="1000000000" /> <!--1GB-->
<p id="filedrag">Drag and drop a video file from your computer here. Or use the 'File upload' button below.</p><!--dragFileHere-->
<label class="control-label" for="fileselect">Files to upload:</label>
<input type="file" id="fileselect" name="fileselect[]" /> <!--multiple="multiple"-->
<button class="btn" id="submitbutton" type="submit">Upload Files</button> <!--hidden via js/css-->
<div class="progress progress-striped active">
<div class="bar" style="width: 0%;"></div>
</div>
<label class="hide" for="video-title">Title</label>
<input type="text" id="video-title" class="span4" placeholder="Video Title"/>
<label class="control-label" for="video-category">Category</label>
<select id="video-category" name="videoCategory" class="span4">
<option value="Autos">Autos & Vehicles</option>
<option value="Music">Music</option>
.......
<option value="Entertainment" selected>Entertainment</option>
</select>
<input id="token" type="text" placeholder="token"/> <!--will be hidden-->
</div>
</fieldset>
</form>
by leaving the action attribute blank, (and using script I already had in place to respond to user interaction) I can ensure the form is submitted programmatically via javascript:
<script src=http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js></script>
<script src=_js/video_app.js" type="text/javascript></script>
<script>
/*
filedrag.js - HTML5 File Drag & Drop demonstration
Featured on SitePoint.com
Developed by Craig Buckler (#craigbuckler) of OptimalWorks.net (without jQuery)
*/
// output information
function Output(msg) {
$('#messages').html(msg + $('#messages').html());
}
// file drag hover
function FileDragHover(e) {
e.stopPropagation();
e.preventDefault();
$(this).addClass("hover");
}
function FileDragOut(e) {
$(this).removeClass("hover");
}
// file selection
function FileSelectHandler(e) {
// cancel event and hover styling
FileDragHover(e);
// fetch FileList object
var files = e.target.files || e.dataTransfer.files;
// process all File objects
for (var i = 0, f; f = files[i]; i++) {
ParseFile(f); //prints file data to div and optionally displays content of selected file
UploadFile(f); //uploads file to server
}
}
// output file information
function ParseFile(file) {
videoName = file.name;
videoType = file.type;
videoURL = "http://localhost/"+videoName;
videoCategory = $('#video-category').val();
Output(
"</strong> type: <strong>" + file.type +
"</strong> size: <strong>" + file.size +
"</strong> bytes</p>"
);
// sets a default value because a title is needed for youtube to send response
if( $('#video-title').val() == $('#video-title').attr('placeholder') ) {
$('#video-title').val(videoName);
}
var reader = new FileReader();
reader.onload = function(e) {
var fileContents = e.target.result;
Output(
'<img src="'+e.target.result+'"/>'
);
}
reader.readAsDataURL(file);
//get upload token
ytVideoApp.prepareSyndicatedUpload(videoName, videoCategory);
}
// upload video files
function UploadFile(file) {
var xhr = new XMLHttpRequest();
if (xhr.upload && file.size <= $('#MAX_FILE_SIZE').val()) { //&& file.type == "video/mp4" or video/*
xhr.upload.addEventListener("progress", function(e) {
var pc = Math.ceil(e.loaded / e.total * 100);
}, false);
// file received/failed
xhr.onreadystatechange = function(e) {
if (xhr.readyState == 4) {
if(xhr.status == 200) { //success
} else { //fail
}
}
};
// start upload
xhr.open("POST", 'upload.php', true); //$("#upload").attr('action')
xhr.setRequestHeader("X_FILENAME", file.name);
xhr.send(file);
}
}
// initialize
function Init() {
// file select
$('#fileselect').change(FileSelectHandler);
// is XHR2 available?
var xhr = new XMLHttpRequest();
if (xhr.upload) {
// file drop
$('#filedrag').bind('dragover', FileDragHover);
$('#filedrag').bind('dragleave', FileDragOut);
//I can't get the below line to work, so I've used the ugly fallback
//$('#filedrag').bind('drop', FileSelectHandler);
document.getElementById('filedrag').addEventListener("drop", FileSelectHandler, false);
filedrag.style.display = "block";
// remove submit button
submitbutton.style.display = "none";
}
}
// call initialization file
if (window.File && window.FileList && window.FileReader) {
Init();
}
</script>
_js/video_app.js:
/**
* Zend Framework
* #package Zend_Gdata
....
/**
* provides namespacing for the YouTube Video Application PHP version (ytVideoApp)
**/
var ytVideoApp = {};
/**
* Sends an AJAX request to the server to retrieve a list of videos or
* the video player/metadata. Sends the request to the specified filePath
* on the same host, passing the specified params, and filling the specified
* resultDivName with the resutls upon success.
* #param {String} filePath The path to which the request should be sent
* #param {String} params The URL encoded POST params
* #param {String} resultDivName The name of the DIV used to hold the results
*/
ytVideoApp.sendRequest = function(filePath, params, resultDivName) {
if (window.XMLHttpRequest) {
var xmlhr = new XMLHttpRequest();
} else {
var xmlhr = new ActiveXObject('MSXML2.XMLHTTP.3.0');
}
xmlhr.open('POST', filePath);
xmlhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlhr.onreadystatechange = function() {
var resultDiv = document.getElementById(resultDivName);
if (xmlhr.readyState == 1) {
resultDiv.innerHTML = '<b>Loading...</b>';
} else if (xmlhr.readyState == 4 && xmlhr.status == 200) {
if (xmlhr.responseText) {
resultDiv.innerHTML = xmlhr.responseText;
}
} else if (xmlhr.readyState == 4) {
alert('Invalid response received - Status: ' + xmlhr.status);
}
}
xmlhr.send(params);
}
ytVideoApp.prepareSyndicatedUpload = function(videoTitle, videoCategory, fileContents) {
var filePath = '_scripts/operations.php';
var params = 'operation=create_upload_form' +
'&videoTitle=' + videoTitle +
'&videoCategory=' + videoCategory;
ytVideoApp.sendRequest(filePath, params, ytVideoApp.SYNDICATED_UPLOAD_DIV);
}
_scripts/operations.php:
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_YouTube');
Zend_Loader::loadClass('Zend_Gdata_AuthSub');
Zend_Loader::loadClass('Zend_Gdata_App_Exception');
/*
* The main controller logic.
*
* POST used for all authenticated requests
* otherwise use GET for retrieve and supplementary values
*/
session_start();
setLogging('on');
generateUrlInformation();
if (!isset($_POST['operation'])) {
// if a GET variable is set then process the token upgrade
if (isset($_GET['token'])) {
updateAuthSubToken($_GET['token']);
} else {
if (loggingEnabled()) {
logMessage('reached operations.php without $_POST or $_GET variables set', 'error');
header('Location: add-content.php');
}
}
}
$operation = $_POST['operation'];
switch ($operation) {
....
case 'create_upload_form':
createUploadForm($_POST['videoTitle'],
$_POST['videoCategory'],
$_POST['videoContents']);
break;
....
default:
unsupportedOperation($_POST);
break;
}
function createUploadForm($videoTitle, $videoCategory, $nextUrl = null) {
$httpClient = getAuthSubHttpClient();
$youTubeService = new Zend_Gdata_YouTube($httpClient);
$newVideoEntry = new Zend_Gdata_YouTube_VideoEntry();
$newVideoEntry->setVideoTitle($videoTitle);
//make sure first character in category is capitalized
$videoCategory = strtoupper(substr($videoCategory, 0, 1))
. substr($videoCategory, 1);
$newVideoEntry->setVideoCategory($videoCategory);
// convert videoTags from whitespace separated into comma separated
$tokenHandlerUrl = 'https://gdata.youtube.com/action/GetUploadToken';
try {
$tokenArray = $youTubeService->getFormUploadToken($newVideoEntry, $tokenHandlerUrl);
if (loggingEnabled()) {
logMessage($httpClient->getLastRequest(), 'request');
logMessage($httpClient->getLastResponse()->getBody(), 'response');
}
} catch (Zend_Gdata_App_HttpException $httpException) {
print 'ERROR ' . $httpException->getMessage()
. ' HTTP details<br /><textarea cols="100" rows="20">'
. $httpException->getRawResponseBody()
. '</textarea><br />'
. '<a href="session_details.php">'
. 'click here to view details of last request</a><br />';
return;
} catch (Zend_Gdata_App_Exception $e) {
print 'ERROR - Could not retrieve token for syndicated upload. '
. $e->getMessage()
. '<br /><a href="session_details.php">'
. 'click here to view details of last request</a><br />';
return;
}
$tokenValue = $tokenArray['token'];
$postUrl = $tokenArray['url'];
// place to redirect user after upload
if (!$nextUrl) {
$nextUrl = $_SESSION['homeUrl'];
}
//instead of outputting the form below, send variables (json???) to be interpreted by xmlhr in _js/video_app.js
//print <<< END
//<br />
//<p>url: ${postUrl}?nexturl=${nextUrl}</p>
//<form id="uploadToYouTubeForm" action="temp.php" method="post" enctype="multipart/form-data">
//<input id="uploadToYouTube" name="file" type="file" onchange="autoUploadToYouTube();" /><br/>
//token: <input id="token" name="token" type="text" value="${tokenValue}"/><br/>
//<input value="Manual upload" type="submit" />
//</form>
//END;
//}
So the first javascript listens for the drag & drop (on the div) or change() event for the input type="file". The form is not actually submitted, but data is gathered and and sent via ajax to the php script which returns the token and url needed for upload. The original PHP script then outputs a form to select the file (and a hidden field containing the token). INSTEAD of that, I want to pass the url and token as variables and use the XMLHttpRequest to put those variables in the action attribute of the form as well set the key to a hidden input field's value. Then the field can be submitted via $('#uploadToYouTubeForm').submit();
The only problem that may arise is sending additional information to the youtube app, I'm hoping it will simply ignore it or i may need to programmatically remove the fields that youtube won't accept (title, category, max file size)....

How to pass a php code in a javascript function?

I want to append the name of the file uploaded into ('.list'). The name of the file has to be the name which it is called in the server when it is uploaded. For example I could have 2 files but one is known as mountains.png and the other mountains2.png.
But the problem is that how could I pass $_FILES["fileImage"]["name"] as argument to my js function and then append it because the javascript function and the php script are on seperate pages (even though the php script does do a call back to the javascript function)?
UPDATE
Below is the javascript code:
Below is the form code (QandATable.php)
<form action='imageupload.php' method='post' enctype='multipart/form-data' target='upload_target' onsubmit='startImageUpload(this);' class='imageuploadform' >
<p>Image File: <input name='fileImage' type='file' class='fileImage' />
<input type='submit' name='submitImageBtn' class='sbtnimage' value='Upload' />
</p>
<ul class='list'></ul>
</form>
Below is the javascript function (QandATable.php)
function stopImageUpload(success){
var nameimagefile = <?php echo $nameimagefile?>;
var result = '';
if (success == 1){
result = '<span class="msg">The file was uploaded successfully!</span><br/><br/>';
$('.listImage').append(nameimagefile + '<br/>');
}
else {
result = '<span class="emsg">There was an error during file upload!</span><br/><br/>';
}
return true;
}
Below is the php script (imageupload.php):
$result = 0;
$nameimagefile = '';
if( file_exists("ImageFiles/".$_FILES['fileImage']['name'])) {
$parts = explode(".",$_FILES['fileImage']['name']);
$ext = array_pop($parts);
$base = implode(".",$parts);
$n = 2;
while( file_exists("ImageFiles/".$base."_".$n.".".$ext)) $n++;
$_FILES['fileImage']['name'] = $base."_".$n.".".$ext;
move_uploaded_file($_FILES["fileImage"]["tmp_name"],
"ImageFiles/" . $_FILES["fileImage"]["name"]);
$result = 1;
$nameimagefile = $_FILES["fileImage"]["name"];
}
else
{
move_uploaded_file($_FILES["fileImage"]["tmp_name"],
"ImageFiles/" . $_FILES["fileImage"]["name"]);
$result = 1;
$nameimagefile = $_FILES["fileImage"]["name"];
}
?>
<script language="javascript" type="text/javascript">window.top.window.stopImageUpload(<?php echo $result;?>);</script>
You can simply take the value $_FILE filename into a php variable than echo it using
var yourjasvariable=<?php echo $yourvariable?>;
and use this js variable in append method. :-)
You could chose AJAX to do what you want.
Write your data in JSON. JSON can be read from PHP and JavaScript
- read the JSON to get data in PHP
- read the AJAX result (the JSON) to get the data from PHP
I would do something like this (untested example)
AJAX js part
<form method='post' enctype='multipart/form-data' onsubmit='startAjaxImageUpload(this);' >
...
</form>
/*
* ajax functions
*/
function startAjaxImageUpload(event){
/* Collect your formdatas as json with jquery this datas will be sent to php*/
var formDatas = {
'value1' : $('input[test1=eid]').val(),
'value2' : $('input[id=test2_id]').val(),
......
'value3' : $('input[id=test3_id]').val()
};
$.ajax({
cache: false,
url: "imageupload",
data: formDatas,
success: function(data) {
// data is the json Result from php => imageupload.php do what u want with them in js
// use the next line if u wanna see which json datas comes back from php if the ajax call wass successfull
// console.log("data is %o, data);
// ....
}
error:function(data){
// error function
// data is the json Result from php => imageupload.php do what u want with them in js
// use the next line if u wanna see which json datas comes back from php if the ajax call wass successfull
// console.log("data is %o, data);
alert(damn, something went wrong);
}
})
}
PHP part, imageupload.php
$result = 0;
$nameimagefile = '';
.....
// if done ure work on server side and no error was found, pass the result back to starAjaxImageUpload success function
return $nameimagefile = $_FILES["fileImage"]["name"];
}else
// abbort ajax, ajax error function will used
return false
}

Send/receive data via jQuery to/from PHP

I am using this code to make the user input a name to create a folder. I have modified the code to try and send the form data via jQuery and receive the success/failure message from PHP through jQuery.
However, when I enter the name of the folder, nothing happens. No folder is created nor any error displayed. Firebug does not show any error either.
This is the code I have till now:
create.php:
<html>
<head><title>Make Directory</title></head>
<body>
<div id="albumform">
<form id="album_form" method="post" action="createAlbum.php" enctype="multipart/form-data">
<p id="message" style="display:none;">
<?php echo (isset($success)?"<h3>$success</h3>":""); ?>
<?php echo (isset($error)?'<span style="color:red;">' . $error . '</span>':''); ?>
</p>
<input type="text" id="create_album" name="create_album" value="" />
<input type="button" onclick="return checkForm('album_form');" id="btn_album" name="btn_album" value="Create" />
</form>
</div>
</body>
</html>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script type="text/javascript">
/* $("#btn_album").click(function() { */
function checkForm(form) {
//create post data
var postData = {
"create_album" : $("#create_album").val()
};
//make the call
$.ajax({
type: "POST",
url: "createAlbum.php",
data: postData, //send it along with your call
success: function(response){
$('#message').fadeIn();
}
});
/* }); */
}
</script>
createAlbum.php:
<?php
/**********************
File: createDir.php
Author: Frost
Website: http://www.slunked.com
***********************/
// set our absolute path to the directories will be created in:
$path = $_SERVER['DOCUMENT_ROOT'] . '/web/photos/images/';
if (isset($_POST['btn_album'])) {
// Grab our form Data
$dirName = isset($_POST['create_album'])?$_POST['create_album']:false;
// first validate the value:
if ($dirName !== false && preg_match('~([^A-Z0-9]+)~i', $dirName, $matches) === 0) {
// We have a valid directory:
if (!is_dir($path . $dirName)) {
// We are good to create this directory:
if (mkdir($path . $dirName, 0775)) {
$success = "Your directory has been created succesfully!<br /><br />";
}else {
$error = "Unable to create dir {$dirName}.";
}
}else {
$error = "Directory {$dirName} already exists.";
}
}else {
// Invalid data, htmlenttie them incase < > were used.
$dirName = htmlentities($dirName);
$error = "You have invalid values in {$dirName}.";
}
}
?>
There are at least two seperate problems with your code:
In the php-file, you check if $_POST['btn_album'] is set. This field is not sent as it is not part of your ajax-request (You're only sending "create_album" : $("#create_album").val()). So the code that creates the folder is never executed.
Another problem is the part
<?php echo (isset($success)?"<h3>$success</h3>":""); ?>
<?php echo (isset($error)?'<span style="color:red;">' . $error . '</span>':''); ?>
in your response-message. This code is evaluated when the page loads, not during your ajax-request, so the php-variables $success and $error will always be undefined. You have to return those response-messages as response to the actual request and then use javascript to display them.
The ajax request has a bad habit of failing silently.
You should use jQuery post and take advantage of .success(), .complete(), and .error() functions to track your code.
Also use the console.log() to check if the parameters are sent corectly. I'll try out the code myself to see the problem.
http://api.jquery.com/jQuery.post/
Due to the nature of the $.ajax request, $_POST['btn_album'] is not sent. So your php file gets here
if (isset($_POST['btn_album'])) {
and returns false.
also you need to echo $error to get a response.

Categories