php ajax 文件上传失败 - 部分文件上传错误

php ajax file upload not working - partial file upload error

我已经使用 html、ajax 和 php 编写了用于上传文件以及其他表单输入的代码。我正在使用 ajax 提交表单。一切都在一台服务器上工作,但是当我将代码移动到新服务器时,我不断收到部分文件上传错误。

示例代码如下

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>

我要设置一些来自 javascript 的参数,所以,

$("#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);
        }
    });
});

并且在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
}

如果直接从 PHP 提交表单,上传将有效。我查看并比较了 apache 和 php 配置以检查是否有任何遗漏。下面是apache和php的服务器配置。在 Server1 和 Server2 中都可以上传。

服务器 1:

Apache/2.4.6 (RHEL 7.9)
PHP 7.3.29

服务器 2:

Apache/2.4.37 (RHEL 8.4)
PHP 7.4.19

服务器 3(新服务器):

Apache/2.4.46 (RHEL 7.9)
PHP 7.4.12

我尝试通过设置header("Connection: close");关闭连接,增加max_upload_sizepost_max_size但没有用。

这可能是什么原因?

下面还给出了示例负载:

------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--

我最近发现问题是由于服务器中的Mod 安全规则引起的。 我通过在 modesecurity.conf 中设置 SecRuleEngine Off 禁用了 Mod 安全性,尽管这不是一个好的解决方案。如果有人知道如何在不关闭此模块的情况下执行此操作,请更新。