As a follow up to Why is $_FILES[] always empty?:
When uploading a file via AJAX with PhP, one generally does the following (Iām new to this so please tell me if there is a better way to do this):
- Have one file with a form and javascript where you setup and send your
XMLHttpRequest
, e.g. upload_form.php - Have another, external php file to process the upload request, e.g. upload.php
My question is this:
Is it possible to abort the XMLHttpRequest from within the external upload.php file?.
The reason for wanting to do this is that if the file already exists on the server, I'd like to abort the XMLHttpRequest
rather than making the user wait until the upload has completed to be informed of the failure.
Some images to illustrate the problem:
I throttled the speed in the network tab in order to exaggerate the problem.
The user uploads a file that DOES NOT exist on the server in the uploads directory:
The user uploads a file that DOES exist on the server in the uploads directory:
Some code to illustrate the problem:
upload_form.php:
<!-- enctype and method added on suggestions from previous question -->
<form class="form" id="upload_form" enctype="multipart/form-data" method="POST">
<input type="file" name="file_to_upload" id="file_to_upload"><br>
<input class="button" type="submit" value="Upload">
</form>
<script>
const upload_form = document.getElementById('upload_form');
var file_to_upload = document.getElementById('file_to_upload');
upload_form.addEventListener("submit", upload_file);
function upload_file (e) {
e.preventDefault();
const xhr = new XMLHttpRequest()
xhr.open("POST", "upload.php");
xhr.upload.addEventListener("progress", e => {
const percent = e.lengthComputable ? (e.loaded / e.total) * 100 : 0;
console.log(percent.toFixed(0) + "%");
});
// ================= MAIN PART OF QUESTION ===================
// Can I force this to fire from upload.php if file exists?
xhr.addEventListener("abort", e => {
console.log(e);
});
// ===========================================================
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// update some response area here
}
};
xhr.send(new FormData(upload_form));
}
</script>
upload.php:
<?php
$target_path = "uploads/".basename($_FILES["file_to_upload"]["name"]);
$uploaded_file = $_FILES['file_to_upload']['tmp_name'];
$upload_ok = true;
$errors = [];
// ================= MAIN PART OF QUESTION ==========================
// I want this to cause the abort event to fire on the XMLHttpRequest
if (file_exists($target_path)) {
$upload_ok = false;
array_push($errors, 'The file already exists on the server. Please rename the file and try again.');
}
// ==================================================================
if(!$upload_ok) {
echo 'The file was not uploaded because:<br>';
foreach ($errors as $err) {
echo $err.'<br>';
}
} else {
if(move_uploaded_file($_FILES["file_to_upload"]["tmp_name"], $target_path)) {
echo 'File uploaded successfully';
} else {
echo 'Something went wrong. Please try again.';
}
}
?>
I've tried checking different combinations of readyState
and status
in upload_form.php but this hasn't helped.