Reputation: 233
I am having problem with my cancel button when trying to cancel my upload and I needs some help in probably changing the design of my code a little.
The problem:
The "cancelaudio.php" page does not have the information it needs until after the "audioupload.php" script has been run. It's a cart and horse situation. If the client clicks the cancel button during the HTTP request, the "audioupload.php" script (on the server side) never gets executed. However the client-side activities in jQuery would still get run.
The solution I want to acheive:
Client fills in the form and submits it, resulting an a POST request, accompanied by the file. The POST request may take several seconds to complete, depending on the size of the file, speed of the connections, etc.
Only after the HTTP upload has completed for all of the files, will PHP gain control. Your PHP "action" script on the server gets control via a POST-method request. If any errors occurred during the upload, $_FILES['error'] will be loaded with the right code. At this point you can check for values in $_FILES, move_uploaded_file(), load the file name into the $_SESSION array, etc.
So to sum up, if the human client clicks a "cancel button" while the POST request is in process (or before starting the upload), and this causes cancellation of the file upload, the PHP "action" script that handles the uploads never gets control. The server never has an opportunity to move the uploaded file and load the variables into the database or session array.
I just need help on coding the problem to be able to reach the solution. Can anybody help? Below are the necessary code:
AUDIOUPLOAD.PHP
<?php
ini_set('display_errors',1);
error_reporting(E_ALL);
// connect to the database
include('connect.php');
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
die();
}
$result = 0;
if( file_exists("AudioFiles/".$_FILES['fileAudio']['name'])) {
$parts = explode(".",$_FILES['fileAudio']['name']);
$ext = array_pop($parts);
$base = implode(".",$parts);
$n = 2;
while( file_exists("AudioFiles/".$base."_".$n.".".$ext)) $n++;
$_FILES['fileAudio']['name'] = $base."_".$n.".".$ext;
move_uploaded_file($_FILES["fileAudio"]["tmp_name"],
"AudioFiles/" . $_FILES["fileAudio"]["name"]);
$result = 1;
}
else
{
move_uploaded_file($_FILES["fileAudio"]["tmp_name"],
"AudioFiles/" . $_FILES["fileAudio"]["name"]);
$result = 1;
}
$audiosql = "INSERT INTO Audio (AudioFile)
VALUES (?)";
if (!$insert = $mysqli->prepare($audiosql)) {
// Handle errors with prepare operation here
}
//Dont pass data directly to bind_param store it in a variable
$insert->bind_param("s",$aud);
//Assign the variable
$aud = 'AudioFiles/'.$_FILES['fileAudio']['name'];
$insert->execute();
if ($insert->errno) {
// Handle query error here
}
$insert->close();
$lastAudioID = $mysqli->insert_id;
$_SESSION['lastAudioID'] = $lastAudioID;
$_SESSION['AudioFile'] = $_FILES["fileAudio"]["name"];
$audioquestionsql = "INSERT INTO Audio_Question (AudioId, QuestionId)
VALUES (?, ?)";
if (!$insertaudioquestion = $mysqli->prepare($audioquestionsql)) {
// Handle errors with prepare operation here
echo "Prepare statement err audioquestion";
}
$qnum = (int)$_POST['numaudio'];
$insertaudioquestion->bind_param("ii",$lastAudioID, $qnum);
$insertaudioquestion->execute();
if ($insertaudioquestion->errno) {
// Handle query error here
}
$insertaudioquestion->close();
?>
CANCELAUDIO.PHP
<?php
// connect to the database
include('connect.php');
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
die();
}
unlink("AudioFiles/" . $_SESSION['AudioFile']);
$delete = $mysqli->prepare('DELETE FROM Audio WHERE AudioId = ?');
$delete->bind_param("i",$_SESSION['lastAudioID']);
$delete->execute();
$deleteaud = $mysqli->prepare('DELETE FROM Audio_Question WHERE AudioId = ?');
$deleteaud->bind_param("i",$_SESSION['lastAudioID']);
$deleteaud->execute();
?>
HTML FORM CODE:
<form action='audioupload.php' method='post' enctype='multipart/form-data' target='upload_target_audio' onsubmit='return audioClickHandler(this);' class='audiouploadform' >
Audio File: <input name='fileAudio' type='file' class='fileAudio' /></label><br/><br/><label class='audiolbl'>
<input type='submit' name='submitAudioBtn' class='sbtnaudio' value='Upload' /></label>
<input type='hidden' class='numaudio' name='numaudio' value='" + GetFormAudioCount() + "' />
<input type='reset' name='audioCancel' class='audioCancel' value='Cancel' /></label>
<iframe class='upload_target_audio' name='upload_target_audio' src='#' style='width:300px;height:300px;border:0px;solid;#fff;'></iframe></form>
JQUERY CODE:
function startAudioUpload(audiouploadform){
$(audiouploadform).find('.audiof1_upload_process').css('visibility','visible');
$(audiouploadform).find('.audiof1_cancel').css('visibility','visible');
$(audiouploadform).find('.audiof1_upload_form').css('visibility','hidden');
sourceAudioForm = audiouploadform;
$(audiouploadform).find(".audioCancel").on("click", function(event) {
$('.upload_target_audio').get(0).contentwindow
$("iframe[name='upload_target_audio']").attr("src", "cancelaudio.php");
return stopAudioUpload(2);
});
return true;
}
Upvotes: 3
Views: 965
Reputation: 9487
Ok I'll try something from what I understood.
The user submits a file using the form. This could take some time, so when the user clicks on "Cancel", 2 cases are possible:
The form (and its data, i.e. the file content) is still being sent out by the browser and is not finished uploading. In that case, all you have to do is cancel the form submission. Ask the browser to stop it.
That way, the audioupload.php
will never execute, and you won't need to remove it by calling cancelaudio.php
.
When the browser completed the file upload / form submission, there's a short time frame where the server is still processing the data and has not responded to you yet. In that case, the uploaded file may or may not be saved (we don"t know). You need to call your cancelaudio.php
page to delete it from the hard drive.
Only one of the 2 cases will be true, but you can do both actions since none will conflict with the other one.
The answer to first case is here (since you're using an <iframe>
to submit the form) : Is it possible to cancel file upload that uses hidden iframe?
The anwser to second case is to always make an Ajax call to cancelaudio.php
, just in case the file has been processed and saved but we haven't been notified (well, the time frame is short, but it still can happen).
Upvotes: 0
Reputation: 709
First you could try visiting this link about Session Upload Progress, this should show you how to stop the progress of the upload without killing the session :)
You could try killing the MySQL connection then re-opening it, i assume this would be one method to stop the connection... i assume if you use the code in conjunction with a cancel button (e.g onclick->blah blah coding blah) you could cancel the connection then return it once connection has been terminated?
here's a link -> PHP: MySQL_close
after this just write a simple line of code to start running the action scripts (point to the function that you need to run), this should allow you to continue running the scripts and not loose the session that you need.
ps. I'm not entirely sure this will work... just thinking logically :P...
Upvotes: 2
Reputation: 122
try this with jquery:
$(".audioCancel").live("click", function(){
var file = $(".fileAudio").val();
var canc = "Cancel";
$.post("CANCELAUDIO.PHP", {file:file,canc:canc}, function(result){
alert(result);
window.location.reload();
});
});
then in your php add this:
$file = $_POST["file"];
$canc = $_POST["canc"];
if($canc){
unlink("AudioFiles/" . $canc);
}else{
unlink("AudioFiles/" . $_SESSION['AudioFile']);
}
try this also:
When the session.upload_progress.enabled INI option is enabled, PHP will be able to track the upload progress of individual files being uploaded. This information isn't particularly useful for the actual upload request itself, but during the file upload an application can send a POST request to a separate endpoint (via XHR for example) to check the status.
The upload progress will be available in the $_SESSION superglobal when an upload is in progress, and when POSTing a variable of the same name as the session.upload_progress.name INI setting is set to. When PHP detects such POST requests, it will populate an array in the $_SESSION, where the index is a concatenated value of the session.upload_progress.prefix and session.upload_progress.name INI options. The key is typically retrieved by reading these INI settings, i.e.
<?php
$key = ini_get("session.upload_progress.prefix") . $_POST[ini_get("session.upload_progress.name")];
var_dump($_SESSION[$key]);
?>
It is also possible to cancel the currently in-progress file upload, by setting the $_SESSION[$key]["cancel_upload"] key to TRUE. When uploading multiple files in the same request, this will only cancel the currently in-progress file upload, and pending file uploads, but will not remove successfully completed uploads. When an upload is cancelled like this, the error key in $_FILES array will be set to UPLOAD_ERR_EXTENSION.
http://php.net/manual/en/session.upload-progress.php
Upvotes: 0