'php ajax file upload not working - partial file upload error

I've written code for uploading a file along with other form inputs using html, ajax and php. I'm submitting the form using ajax. Everything is working in one server, but when I moved the code to a new server, I keep getting PARTIAL FILE UPLOAD ERROR.

Sample code is given below

HTML:

<form id="gal-form" class="form-gallery" enctype="multipart/form-data">
    <input type="hidden" id="gal_id" name="id" value="">
    <div class="up-types">
        <div class="input-group mb-3 display-none check-links">
            <span class="input-group-text">Links to</span>
            <input type="text" value="ebooks" disabled="">
            <input type="text" name="links[]" class="form-control" data-type="ebooks" id="links_to_3" value="">
        </div>
        <div class="input-group mb-3 display-none check-links">
            <span class="input-group-text">Links to</span>
            <input type="text" value="handbooks" disabled="">
            <input type="text" name="links[]" class="form-control" data-type="handbooks" id="links_to_4" value="">
        </div>
        <div class="input-group mb-3 display-none check-links">
            <span class="input-group-text">Links to</span>
            <input type="text" value="manuals" disabled="">
            <input type="text" name="links[]" class="form-control" data-type="manuals" id="links_to_5" value="">
        </div>
    </div>
    <div class="form-group">
        <label for="gal_title">Title</label>
        <input type="text" class="form-control" id="gal_title" name="title" placeholder="Add a title here..">
    </div>
    <div class="form-group">
        <label for="gal_title">Category</label>
        <input id="gallery_tags" class="form-control" name="tags[]" type="text" value="" placeholder="Add a category here..">
    </div>
    <div class="form-group">
        <label>File upload <span class="text-danger">*Only PDF, MP4, WEBM, OGG, JPG, JPEG, &amp; PNG files are allowed. Please try to upload images/videos of a specific aspect ratio</span></label>
        <input type="file" name="gal" id="gal-file" class="file-upload-default">
        <div class="input-group col-xs-12">
            <input type="text" class="form-control file-upload-info" disabled="" placeholder="Upload File">
            <span class="input-group-append">
                <button class="file-upload-browse btn btn-primary" type="button">Browse</button>
            </span>
        </div>
    </div>
    <div class="form-group">
        <label for="event_text">Description</label>
        <textarea class="form-control" id="media_desc" name="desc" rows="4" aria-hidden="true"></textarea>
    </div>
    <button type="submit" id="gal-button" class="btn btn-primary mr-2">Submit</button>
</form>

I've to set some parameters from javascript, so,

$("#gal-form").on('submit', function(e) {
    e.preventDefault();
    var desc = "Some description here";

    if ($('#gal_title').val() == '') {
        $('#display-msg').html('<span style="color:red">Please enter title name...</span>');
        return false;
    } else if ($('#gal-file').get(0).files.length === 0 && !desc) {
        $('#display-msg').html('<span style="color:red">Please enter a description or choose a file to upload...</span>');
        return false;
    } 

    var formData = new FormData(this);
    var values = $("input[name='links[]']:enabled").map(function() {
        let id = this.id.split("_").pop();
        let link = $(this).data("type");
        if (this.value) {
            link += "/" + this.value;
        }
        return {
            id: id,
            link: link
        };
    }).get();
    formData.append('links_to', JSON.stringify(values));
    formData.set('desc',desc);

    $.ajax({
        type: 'POST',
        url: 'url',
        data: formData,
        dataType: 'json',
        contentType: false,
        cache: false,
        processData: false,
        success: function(obj) {
            if (obj.success) {
                window.location.reload();
            } else {
                alertItem(obj.error);
            }
        },
        error: function(request, status, error) {
            alertItem(request.responseText);
        }
    });
});

And in PHP,

$uploadStatus = 1; 
$data = array();
if(!empty($_FILES["gal"]["name"])){ 
    $file_name = pathinfo(basename($_FILES["gal"]["name"]),PATHINFO_FILENAME);
    $fileType = pathinfo(basename($_FILES["gal"]["name"]), PATHINFO_EXTENSION);

    $fileName = $this->generateSlug($file_name).'_'.time().'.'.$fileType; 
    $targetFilePath = $fileName; 
        
    $allowTypes = array('pdf', 'mp4', 'webm', 'ogg', 'jpg', 'png', 'jpeg'); 
    if(in_array(strtolower($fileType), $allowTypes)){ 
        if(move_uploaded_file($_FILES["gal"]["tmp_name"], $targetFilePath)){ 
            $data['file'] = $fileName;
        }else{ 
            $uploadStatus = 0; 
            return  array('error'=>$_FILES["error"])); 
        } 
    }else{ 
        $uploadStatus = 0; 
        return  array('error'=>'Sorry, only PDF, MP4, WEBM, OGG, JPG, JPEG, & PNG files are allowed to upload.'); 
    } 
} 

if($uploadStatus == 1){ 
    //Add to database
}

Uploading will work if submit the form directly from PHP. I've looked through and compared apache and php configurations to check if there is anything missing. Below are the server configurations of apache and php. Uploading works in both Server1 and Server2.

Server 1:

Apache/2.4.6 (RHEL 7.9)
PHP 7.3.29

Server 2:

Apache/2.4.37 (RHEL 8.4)
PHP 7.4.19

Server 3 (New Server):

Apache/2.4.46 (RHEL 7.9)
PHP 7.4.12

I tried to close the connection by setting header("Connection: close");, increased max_upload_size, post_max_size but no use.

What could be a possible reason for this?

Sample payload is also given below:

------WebKitFormBoundaryj7GC6KVa5gPA46RP
Content-Disposition: form-data; name="id"


------WebKitFormBoundaryj7GC6KVa5gPA46RP
Content-Disposition: form-data; name="category[]"

1
------WebKitFormBoundaryj7GC6KVa5gPA46RP
Content-Disposition: form-data; name="links[]"


------WebKitFormBoundaryj7GC6KVa5gPA46RP
Content-Disposition: form-data; name="title"

Test
------WebKitFormBoundaryj7GC6KVa5gPA46RP
Content-Disposition: form-data; name="tags[]"

Cat
------WebKitFormBoundaryj7GC6KVa5gPA46RP
Content-Disposition: form-data; name="gal"; filename="not.png"
Content-Type: image/png


------WebKitFormBoundaryj7GC6KVa5gPA46RP
Content-Disposition: form-data; name="desc"

<p>Test description</p>
------WebKitFormBoundaryj7GC6KVa5gPA46RP
Content-Disposition: form-data; name="links_to"

[{"id":"1","link":"photo"}]
------WebKitFormBoundaryj7GC6KVa5gPA46RP--


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source