Home > OS >  php ajax file upload not working - partial file upload error
php ajax file upload not working - partial file upload error

Time:03-05

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"  enctype="multipart/form-data">
    <input type="hidden" id="gal_id" name="id" value="">
    <div >
        <div >
            <span >Links to</span>
            <input type="text" value="ebooks" disabled="">
            <input type="text" name="links[]"  data-type="ebooks" id="links_to_3" value="">
        </div>
        <div >
            <span >Links to</span>
            <input type="text" value="handbooks" disabled="">
            <input type="text" name="links[]"  data-type="handbooks" id="links_to_4" value="">
        </div>
        <div >
            <span >Links to</span>
            <input type="text" value="manuals" disabled="">
            <input type="text" name="links[]"  data-type="manuals" id="links_to_5" value="">
        </div>
    </div>
    <div >
        <label for="gal_title">Title</label>
        <input type="text"  id="gal_title" name="title" placeholder="Add a title here..">
    </div>
    <div >
        <label for="gal_title">Category</label>
        <input id="gallery_tags"  name="tags[]" type="text" value="" placeholder="Add a category here..">
    </div>
    <div >
        <label>File upload <span >*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" >
        <div >
            <input type="text"  disabled="" placeholder="Upload File">
            <span >
                <button  type="button">Browse</button>
            </span>
        </div>
    </div>
    <div >
        <label for="event_text">Description</label>
        <textarea  id="media_desc" name="desc" rows="4" aria-hidden="true"></textarea>
    </div>
    <button type="submit" id="gal-button" >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--

CodePudding user response:

I recently found that the problem is due to Mod Security rules in the server. I've disabled Mod Security by setting SecRuleEngine Off in modesecurity.conf, though it is not a good solution. Please update if anyone knows how to do this without turning off this module.

  • Related