I am developing a php ajax-based application, and one of it's components is an image upload.
I know ajax is incapable of posting files, since it's Request based, but i did find a nifty iframe work around.
My goal is to send multiple files, but post them individually so i can process the upload and validate serversided, send the result, and then move on to the next file.
I would like to achieve this with a:
<input name="files[]" type="file" multiple=""/>
It all works all fine and dandy, but when it comes to sending them individually.. there doesn't teem to be a possible way.
My original idea was to treat the (element.files) as an array.. So i create duplicate form, and attempted to copy over the input to the other form (that was successfull)
but then when i tried to splice, or remove the unwanted elements so i can submit the form, i couldn't find a way to do it. Nothing worked...
Trying to alter the element.files.length to 1, didn't work
Trying to splice it didn't work..
Trying to just clear the indexes didn't work either...
If anyone could shed a green light, or just blast the ultra red light letting me know that this is not possible w/ an html input, it'll be greatly appreciated.
p.s: Flash isn't an option.
Here's some examples of my failed attempts:
<form name="image_upload" id="image_upload_form" action="image_uploader" method="POST" enctype="multipart/form-data">
<input name="userfile[]" id="filesToUpload" type="file" title="Select Your Files" multiple=""/> <br /><br />
<input type="button" id="imageUploadButton" value="Upload" onclick="valif('image_upload'); return false;" />
</form>
<!-- Hidden Form and File Input -->
<form name="single_image_upload" id="single_image_upload_form" action="image_uploader" method="POST" enctype="multipart/form-data">
<input name="userfile[]" id="fileToUpload" type="file" style="visibility: none; position: absolute; top: 0; left: 0;/>
</form>
<script type="text/javascript">
//This happens on submit
var multi_input = getElementById("image_upload");
var single_input = getElementById("single_image_upload");
single_input = multi_input;
//Assuming there are 2+ files chosen for upload, attempt to only upload the first one.
//Attempt 1
multi_input.files.length = 1;
//Attempt 2
multi_input.files.splice(1);
//Attempt 3
for (x = 1; x < multi_input.files.length; x++) { //skip 0, we wanna keep that one
multi_input.files[x] = null; // or ''.. same difference in this scneario.
}
</script>
Below is the actual code right now, working w/ 1 iframe.... This code works great, however it actually unfortunately sends every single file, every time.. And i just validate the right one on the serverside, but it's not practical, as i shouldn't have to send every single file all the time.
function ajaxUpload(form,url_action,id_element){
var detectWebKit = isWebKit();
form = typeof(form)=="string"?$m(form):form;
//Error Validator
var error="";
if (form==null || typeof(form)=="undefined"){
error += "Invalid Form.\n";
} else if(form.nodeName.toLowerCase()!="form"){
error += "Element Exists but it is not a form.\n";
}
if (id_element==null){
error += "The element of 3rd parameter does not exists.\n";
}
if (error.length>0){
alert("Error in image upload attempt:\n" + error);
return;
}
//Create Frame On The Fly
var iframe = document.createElement("iframe");
iframe.setAttribute("id","ajax-temp-"+rt_img);
iframe.setAttribute("name","ajax-temp-"+rt_img);
iframe.setAttribute("width","0");
iframe.setAttribute("height","0");
iframe.setAttribute("border","0");
iframe.setAttribute("style","width: 0; height: 0; border: none;");
form.parentNode.appendChild(iframe);
window.frames['ajax-temp-'+rt_img].name="ajax-temp-"+rt_img;
//Upload Image
var doUpload = function(){
removeEvent($m('ajax-temp-'+rt_img),"load", doUpload);
var cross = "javascript: ";
cross += "window.parent.upload_result(document.body.innerHTML); void(0);";
$m('ajax-temp-'+rt_img).src = cross;
if(detectWebKit){
remove($m('ajax-temp-'+rt_img));
}else{
setTimeout(function(){ remove($m('ajax-temp-'+rt_img))}, 250);
}
}
//Post Form
addEvent($m('ajax-temp-'+rt_img),"load", doUpload);
form.setAttribute("target","ajax-temp-"+rt_img);
form.setAttribute("action",url_action);
form.setAttribute("method","post");
form.setAttribute("enctype","multipart/form-data");
form.setAttribute("encoding","multipart/form-data");
form.submit();
}
function upload_run() {
var send_index = rt_img;
rt_img += 1;
var li = $('#fileList li:nth-child('+rt_img+')');
var filetype = li.html().substr(-3).toLowerCase();
var skip_mod = '';
//validate file type
if ((filetype != 'jpg') && (filetype != 'png') && (filetype != 'gif')) {
li.append(' - <b>invalid image file</b>');
} else {
li.append(' <img src="'+base_url+'sds_ajax/upload-ani.gif">');
//Initiate File Upload
ajaxUpload($m('image_upload_form'),base_url+'includes/core.php?post_action=image_upload&si='+send_index,li);
}
}
//Get the input and UL list
var button = document.getElementById('imageUploadButton');
var input = document.getElementById('filesToUpload');
var list = document.getElementById('fileList');
//Empty list for now
while (list.hasChildNodes()) {
list.removeChild(ul.firstChild);
}
//Populate List w/ files
rt_max = input.files.length;
for (var x = 0; x < input.files.length; x++) {
//add to list
var li = document.createElement('li');
li.innerHTML = 'Image ' + (x + 1) + ': ' + input.files[x].name;
list.appendChild(li);
}
//Run through created list
rt_img = 0;
upload_run();
//Disable Submit Button
button.disabled=true;
bump
It sounds like you need an iframe per file upload. So what I would do is have hidden fields for every other field in your normal form (in each iframe). Then when you click the submit button, you take all the visible fields and place the values in the corresponding hidden fields for each image. Then call post on each iframe now that they all have the data they need.
Related
Edit 2 : I notices user can upload unlimited files and can take all disk space, how to prevent that?
Edit: since no one answered this question, is there a source I could read to get my answer???
I have a contact form. There are three inputs. I used a jQuery plugin for uploading files. This plugin adds another form element and uploads files by ajax.
I'm kind of beginner but this code is for a customer and a real job so I want to make sure it's safe!
in my view:
<form action="" method="post" enctype="multipart/form-data" >
<input type="text" name="name" />
<input type="number" name="phone" />
<textarea name="enquiry" rows="10" ></textarea>
<div id="upload-div">
<div id="extraupload">Upload</div>
<input type="hidden" name="count" value="0" id="count"/>
<input type="submit" />
$(document).ready(function()
{
var uploadObj = $("#extraupload").uploadFile({
url:"/uplod_url",
fileName:"file",
onSuccess:function(files,data,xhr,pd)
{
data = jQuery.parseJSON(data);
if(data.status == 'success') {
var count = $('#count').val() * 1 + 1;
for(var i=0; i<data.files.length; i++) {
$('<input type="hidden" name="file_'+count+'" value="'+data.files[i]+'">').insertBefore('#extraupload');
$('#count').val(count);
count++;
}
}
},
});
});
</script>
each successful upload,will add one to input count value
and will append an hidden input with the value of uploaded file name.
In php I check for file type and change file name:
upload_url.php:
if ($_FILES['file']['type']=='image/jpeg' || $_FILES['file']['type']=='image/pjpeg') {
$ext = '.jpg';
}
elseif ($_FILES['file']['type']=='image/png') {
$ext = '.png';
}
elseif ($_FILES['file']['type']=='application/pdf') {
$ext = '.pdf';
}
else {
echo json_encode('Only images and pdf files are allowed!');
die();
}
$fileName = md5(uniqid());
$fileName = $fileName.$ext;
move_uploaded_file($_FILES["file"]["tmp_name"], 'image/tmp'.$fileName);
$result = array('status'=> 'success','files' => $fileName);
echo json_encode($result);
After changing the file's name to a unique hash, I save that in a tmp folder.
then when the main form is submitted this is what happens:
//validation method: if that file exists in tmp folder
if(isset($this->request->post['count']) && is_numeric($this->request->post['count'])) {
for($i=1; $i<=$this->request->post['count']; $i++ ) {
if(isset($this->request->post['file_'.$i])){
if(!file_exists('image/tmp/'.$this->request->post['file_'.$i])){
//throw error
}
} else{
//throw error
}
}
}
// hidden input count can only be integer
if(isset($this->request->post['count']) && !is_numeric($this->request->post['count'])) {
//throw error
}
and then mailing the file and saving file name in database(I did not include database part because I'm kind of sure it's ok)
//by every submition delete files in tmp folder older than 1 day
$oldFiles = glob($tmp_dir."*");
$now = time();
foreach ($oldFiles as $oldFile) {
if (is_file($oldFile)) {
if ($now - filemtime($oldFile) >= 60 * 60 * 24) {
unlink($oldFile);
}
}
}
$mail = new Mail();
//Mail Setting and details deleted
//if there's any file uploaded
if($this->request->post['count'] != 0) {
//unique directory for every form submition
$dir_path = 'image/submitted/'.uniqid();
mkdir($dir_path, 0764, true);
//for all hidden inputs move file from tmp folder to $dir_path
for ($i=1; $i <= $this->request->post['count']; $i++) {
$file = $this->request->post['file_'.$i];
rename('image/tmp'.$file, $dir_path.'/'.$file);
$mail->AddAttachment($dir_path.'/'.$file);
}
}
$mail->send();
now my question is: Is it safe this way? especially when I append hidden inputs with file's name and get the number of uploaded files from hidden input count??
This code already works, but I think this might be a security issue.
Thanks a lot for your patience and sorry for my poor english!
ps: I use opencart
There is the general misconception that in AJAX applications are more secure because it is thought that a user cannot access the server-side script without the rendered user interface (the AJAX based webpage). XML HTTP Request based web applications obscure server-side scripts, and this obscurity gives website developers and owners a false sense of security – obscurity is not security. Since XML HTTP requests function by using the same protocol as all else on the web (HTTP), technically speaking, AJAX-based web applications are vulnerable to the same hacking methodologies as ‘normal’ applications.
I made a little page where you can upload picture it is simple php upload. I want everyone to be able to upload images and view everyone else's uploads on the site. How can I display images after they're uploaded? I want to be able to globally track all uploaded images so that everyone can browse them.
I think I need to use "AJAX upload" to do that and maybe javascript to display image after upload... but how?
I tried this:
function GetFileName(){
var fileInput = document.getElementById('fileToUpload');
var fileName = fileInput.value.split(/(\\|\/)/g).pop();
var img = document.createElement('img');
img.src = 'uploads/' + fileName;
img.setAttribute('width', '100px');
img.setAttribute('height', '100px');
img.alt = fileName;
document.body.appendChild(img);
alert(fileName);
}
<form method="post" action="upload.php" enctype="multipart/form-data">
<input type="file" name="fileToUpload" id="fileToUpload" class="upload">
<input type="submit" onclick="GetFileName()" value="Upload Image" name="submit" id="submit">
</form>
This is almost work but the image only display few second and then it disappear.
Try some thing like this in Jquery:
$('#upload').on('click', function() {
var img_name = $('#pic').val();
var file_data = $('#pic').prop('files')[0];
var form_data = new FormData();
form_data.append('file', file_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(output){
if(output) // if success
{
$('#img_container').append('<img src="img_path/"'+ img_name +'>'); // It will display the uploaded image
}
}
});
$('#pic').val(''); /* Clear the file container */
});
Html:
<body>
<input id="pic" type="file" name="pic" />
<button id="upload">Upload</button>
<!-- To display image -->
<div id="img_container">
</div>
</body>
I think the key issue to your question here is in how to keep track of all the uploads. This is likely better solved by relying on a persistence store, like a database, to track of all uploaded files on a global level.
For example, when an upload occurs, you can insert a record into an uploads table in your database like so...
// prepare the statement
$stmt = $db->prepare("INSERT INTO uploads (userId, fileName) VALUES(:userId, :fileName)");
if ($_FILES['upload']['error'] == UPLOAD_ERR_OK) { // no errors
// move the file to a permanent location
$tmpName = $_FILES['upload']['tmp_name'];
move_uploaded_file($tmpName, $uploadDir . "/$tmp_name");
$result = $stmt->execute(
[
'userId' => $_SESSION['userId'], // or however you track the user
'fileName' => $_FILES['upload']['tmp_name'],
]
);
if ($result) {
// record added successfully!
} else {
// failed
}
}
Now you can display all uploaded files by looking at the uploads table in your database and display them to users like so...
// prepare the statement
$start = $_GET['start'] ?? 0;
$stmt = $db->prepare("SELECT userId, fileName FROM uploads LIMIT ?,20");
if ($stmt->execute([$start])) {
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($result as $row) {
echo "<img src='$uploadDir/{$row['fileName']}'>";
}
}
Or you could show only those uploads made by a specific user by adding a WHERE userId = ? clause to that query, for example.
I need help with creating a progress bar for my php upload site. I've got the upload and exctract part sorted but i need help with the progress bar. I'm not sure how to do it. Also, is there a maximum file size for the upload?
HTML
<?php if($message) echo "<p>$message</p>"; ?>
<form enctype="multipart/form-data" method="post" action="">
<label>Choose file (.zip): <input type="file" name="zip_file" /></label>
<br />
<input type="submit" value="Upload" name="submit" value="Upload" />
</form>
PHP
<?php
if($_FILES["zip_file"]["name"]) {
$filename = $_FILES["zip_file"]["name"];
$source = $_FILES["zip_file"]["tmp_name"];
$type = $_FILES["zip_file"]["type"];
$name = explode(".", $filename);
$accepted_types = array(
'application/zip',
'application/x-zip-compressed',
'multipart/x-zip',
'application/x-compressed');
foreach($accepted_types as $mime_type) {
if($mime_type == $type) {
$okay = true;
break;
}
}
$continue = strtolower($name[1]) == 'zip' ? true : false;
if(!$continue) {
$message = "[...] not a .zip file. Please try again.";
}
$target_path = "./".$filename;
if(move_uploaded_file($source, $target_path)) {
$zip = new ZipArchive();
$x = $zip->open($target_path);
if ($x === true) {
$zip->extractTo("./");
$zip->close();
unlink($target_path);
}
$message = "Your .zip file was uploaded and unpacked.";
} else {
$message = "There was a problem with the upload. Please try again.";
}
}
?>
You can make some changes to fit but this works rather well if you want a progress bar. You can add more eventlisteners and make it how you want. I hope this is a good starting point for you.
function uploadFile(){
var file = document.getElementById("zip_file").files[0];
var formdata = new FormData();
formdata.append("zip_file", file);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", function(event) { runprogress(event); } , false);
ajax.addEventListener("load", function(event) {uploadcomplete(event); }, false);
//Target your php file.
ajax.open("POST", "upload.php");
ajax.send(formdata);
}
function runprogress(event){
//The progress %, you might want to Math.round(percent)
var percent = (event.loaded / event.total) * 100;
}
function uploadcomplete(event){
//This will = to your php reply.
var AjaxReply=event.target.responseText;
}
As far as I know you would have to use JavaScript to do this. Post your data through an AJAX call and initialize the progress bar. Over time animating it so that the bar "fills up".
Eventually the AJAX call will complete and will send a response back, upon the completion of the call you can finish the animation. This is how I would assume most progress bars work as they typically go up then stop around 99% until the post returns it's "complete status".
In any case, you would have a progress bar, represented by a <div> for example, with a width that would increase as time goes on, or a number would go up etc... and you would animate this using JavaScript and/or jQuery. Hopefully this will get you started in the right direction.
EDIT
Here's a link to a tutorial describing the steps necessary to upload files to the server using AJAX: Uploading Files with AJAX
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)....
I am trying to submit a form then update some values and submit it again. However, when I do this only the LAST version is being submitted. I get one error for Unsafe Javascript attempt to access frame with URL domain2.com from frame with URL domain1 . Domains, Protocols and Ports must match.
form code:
<form id="hiddenform" method="post" enctype="multipart/form-data" action="http://www.actonsoftware.com/acton/forms/userSubmit.jsp" accept-charset="UTF-8" target="tintest">
the target is a hidden iframe with the id="tintest"
This is my code:
var tbody = $("#vmMainPage table:first tbody");
var lng = tbody[0].rows.length - 1;
var mnstr = "items: ";
$("#vmMainPage table:first tbody tr").each(function(i){
if ((i>0) && (i<(lng-3))) {
item = $(this).children("td").children("a").children("strong").html();
// quantity = "
console.log(item);
$("#hiddenform input#fld_0").val(item);
var $tsta = "";
for ( j=2; j<6; j++)
{
$tst = $("table:eq(2) tr:eq("+j+") td:eq(1)").html();
$tsta = $tsta + $tst +", ";
}
$email = $("table:eq(2) tr:eq(6) td:eq(1)").html();
$("#hiddenform input#fld_2").val($email+"_"+i);
$("#hiddenform input#fld_1").val($tsta);
$("#hiddenform").submit();
}
});
To make sure your requests are not interfering with each other, you can create an iframe for each request and target that.
this can be done with DOM
var cnt=0;
var ifr = document.createElement("iframe");
ifr.name="ifr"+(cnt++);
ifr.style.display="none"
document.getElementById("iframeContainer").appendChild(ifr);
document.forms[0].target=ifr.name;
document.forms[0].submit()
or jQuery
cnt++
$("#iframeContainer").append('<iframe src="about:blank" name="ifr'+cnt+'"></iframe>');
$("#hiddenform").attr("target","ifr"+cnt);
$("#hiddenform").submit();