Skip to content
Advertisement

Why does my XMLHttpRequest aborts on PHP file upload?

I’m trying to upload a video file via AJAX, a XMLHttpRequest and PHP to display the upload progress but the request throws an abort and quickly refreshes the page if I try to upload something.

If I just send the POST request to the PHP file via the form, without AJAX/XMLHttpRequest, the file upload works. But a progress bar would be handy…

The code consists of the HTML form, the JavaScript functions and the PHP upload (I omitted the progress bar HTML code to make it more readable).
HTML:

<form action="" method="post" enctype="multipart/form-data" id="uploadForm">
    <input type="file" accept="video/mp4" class="form-control" name="fileToUpload" id="fileToUpload" onclick="closeFileToBigAlert()" onchange="checkFile(this.files)" required>
    <button onclick="uploadFile()" class="btn">Upload</button>
</form>

JavaScript:

function uploadFile(){
    // Get the file
    var file = document.getElementById("fileToUpload").files[0];

    // Create FormData object and append file as "file"
    var formData = new FormData();
    formData.append("file",file);

    // Create XMLHttpRequest object
    var ajax = new XMLHttpRequest();

    // Add Event Listeners
    ajax.upload.addEventListener("upload-progress", progressHandler, false);
    ajax.addEventListener("load", completeHandler, false);
    ajax.addEventListener("error", errorHandler, false);
    ajax.addEventListener("abort", abortHandler, false);

    // Open upload.php and send POST request
    ajax.open("POST", "upload.php");
    ajax.send(formData);
}

function progressHandler(event){
    // Calculate percentage
    var percent = (event.loaded / event.total) * 100;

    // Insert percentage number into progress bar
    var bar = document.getElementById("upload-progress");
    bar.setAttribute("aria-valuenow", Math.round(percent));
    bar.setAttribute("style", "width: "+ Math.round(percent) +"%");
    bar.innerHTML = Math.round(percent) + "%";
}

function completeHandler(event){
    document.getElementById("status").innerHTML = event.target.responseText;
    var bar = document.getElementById("upload-progress");
    bar.setAttribute("aria-valuenow", "0");
    bar.setAttribute("style", "width: 0%");
    bar.innerHTML = "0%";
}

function errorHandler(event){
    document.getElementById("status").innerHTML = "Upload Failed";
}

function abortHandler(event){
    document.getElementById("status").innerHTML = "Upload Aborted";
}

And PHP:

$fileName = $_FILES["file"]["name"];
$fileTmpLoc = $_FILES["file"]["tmp_name"];
$fileType = $_FILES["file"]["type"];
$fileSize = $_FILES["file"]["size"];
$fileErrorMsg = $_FILES["file"]["error"];

if(move_uploaded_file($fileTmpLoc, "uploads/$fileName")){
    echo "$fileName upload is complete";
} else {
    echo "move_uploaded_file function failed";
}

Any ideas why the request immediately aborts and refreshes the page? The PHP log is empty.

The environment is local via XAMPP

Advertisement

Answer

You’re submitting the form. The JS starts but then the form submits and you navigate to a new page (which aborts all the JS from the previous page).

  1. Remove the onclick attribuete
  2. Bind a submit event handler on the form
  3. Prevent the default behaviour that comes with form submissions

Such:

document.querySelector(`#uploadForm`).addEventListener('submit', event => {
    event.preventDefault();
    // Do everything else
});
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement