【问题标题】:Handle nicely "POST Content-Length of bytes exceeds the limit of" warning处理好“POST Content-Length of bytes超出限制”警告
【发布时间】:2016-03-02 12:14:26
【问题描述】:

美好的一天)我正在构建一个 WordPress 插件 LMS,允许用户通过 AJAX 将他们完成的家庭作业文件附加到他们的答案中。一切正常,除了用户文件超过允许的最大大小的一种情况。在这种情况下,我的 AJAX 调用返回带有以下警告的 HTML:

<b>Warning</b>:  POST Content-Length of XXXXX bytes exceeds the limit of XXXXX bytes in <b>Unknown</b> on line <b>0</b><br />

由于在我的脚本的字符串 0 上生成了这种警告,它会死掉并忽略任何其他指令,因为我的调用而给我留下了这个丑陋的字符串。 你基本上可以忍受它,因为最终用户不会看到它(只是 AJAX 调用不会有想要的结果),但仍然我想知道是否有机会跳过它并很好地处理它?

好的,我已经做了什么样的研究:

  1. 我找到了 Andrew Curioso 的 this 教程,并试图从中做出类似的东西:

    if (isset($_SERVER['CONTENT_LENGTH'])) {
        if ($_SERVER['CONTENT_LENGTH'] > (substr(ini_get('post_max_size'), -1) * 1024 * 1024)) {
            echo 'php errors is so much fun';
        }
    }
    

它没有达到预期的效果,因为我的脚本仍然死亡,只有从 IF 语句中回显附加字符串的积极效果(此外,如果您尝试执行 wp_send_json(errorsArray) 之类的操作,它将不会被执行)。

  1. 使用 display_errors、error_reporting 关闭显示错误。好吧,这不是我在这里需要的,因为它仍然不允许我继续执行脚本并创建自定义错误处理程序。

  2. 我的 WP_DEBUG 设置为 FALSE

我不寻找什么样的建议是手动编辑 max_upload_size、max_post_size 等。因为手动编辑服务器文件超出了插件理念。无论如何,即使您将最大上传大小设置为 10GB,一旦最终用户尝试上传 11GB。

所以,总而言之,众所周知,这种机制已在数千个网站和应用程序上实现,我想知道如何最大限度地提高我的脚本质量,处理这个问题而不会过度杀伤和糟糕的用户体验。

感谢您分享您的想法:)

UPD1 如果有帮助,这是我的 AJAX 调用:

$('#post-assignment-answer').on('click', function (event) {
    event.preventDefault();

    tinymce.triggerSave();
    var answerContent = tinymce.get('assignment_user_input_textarea').getContent();

    var answerFile = $('#assignment-file-upload')[0].files[0];

    var formData = new FormData();

    formData.append('action', 'post_assignment_answer');
    formData.append('security', lucid_single_assignment_params.post_assignment_answer_nonce);
    formData.append('post_id', lucid_single_assignment_params.post_id);
    formData.append('answer_content', answerContent);
    formData.append('answer_file', answerFile);

    $.ajax({
        url: lucid_single_assignment_params.ajax_url,
        type: 'post',
        data: formData,
        contentType: false,
        processData: false,
        success: function (result) {
            console.log(result);
        }
    });
});

UPD2: 添加了AJAX处理php

<?php

/**
 * Post Assignment Answer
 *
 * @version       1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
} // Exit if accessed directly

// Create AJAX call $result
$result = array(
    'fileTypeError' => false,
    'fileSizeError' => false,
    'uploadError' => false
);

// Retrieving current post ID
$post_id = $_POST['post_id'];

// Retrieving WYSIWYG content
$answer_content = '';

if (! (trim($_POST['answer_content']) == '') ) {

    $answer_content = wp_kses_post($_POST['answer_content']);

}

// Updating WYSIWYG meta field
update_post_meta($post_id, '_answer_content', $answer_content);

// Check if user intends to upload a file
if (!empty($_FILES['answer_file'])) {

    // Adding timestamp to file name
    $_FILES['answer_file']['name'] = round(microtime(true)) . '_' . $_FILES['answer_file']['name'];
    $answer_file = $_FILES['answer_file'];

    // Setting up uploaded file type validation
    $supported_types = array(
        'text/plain' // .txt
    );

    $arr_file_type = wp_check_filetype(basename($answer_file['name']));

    $uploaded_type = $arr_file_type['type'];

    // Setting up uploaded file size validation // TODO: This should be optimized
    $allowed_size = 8388608;
    $uploaded_size = $answer_file['size'];

    // Validating, and in a case of success completing upload
    if (!in_array($uploaded_type, $supported_types)) {

        $result['fileTypeError'] = __('The type of file you\'ve provided is not allowed', 'lucidlms');

    } elseif ($uploaded_size > $allowed_size) {

        $result['fileSizeError'] = __('The size of file you\'ve provided is exceeding the maximum upload size', 'lucidlms');

    } else {

        /**
         * Override the default upload path.
         *
         * @param   array   $dir
         * @return  array
         */
        function lucidlms_assignment_upload_dir( $dir ) {
            global $user_ID;

            return array(
                'path'   => $dir['basedir'] . '/lucidlms/assignment/user' . $user_ID,
                'url'    => $dir['baseurl'] . '/lucidlms/assignment/user' . $user_ID,
                'subdir' => ''
            ) + $dir;
        }

        // Register path override
        add_filter( 'upload_dir', 'lucidlms_assignment_upload_dir' );

        $upload = wp_handle_upload($answer_file, array( 'test_form' => false ));

        // Set everything back to normal
        remove_filter( 'upload_dir', 'lucidlms_user_upload_dir' );

        if (isset($upload['error']) && $upload['error'] != 0) {

            $result['uploadError'] = sprintf(__('There was an error uploading your file. The error is: %s', 'lucidlms'), $upload['error']);

        } else {

            // Check if there is an old version of file on the server and delete it
            $existing_answer_file = get_post_meta($post_id, '_answer_file', true);
            if (! empty($existing_answer_file)) {

                global $user_ID;
                $upload_dir = wp_upload_dir();
                $existing_answer_file_name = pathinfo($existing_answer_file['file'], PATHINFO_BASENAME);
                $unlink_path = $upload_dir['basedir'] . '/lucidlms/assignment/user' . $user_ID . '/' . $existing_answer_file_name;
                unlink($unlink_path);

            }

            // Updating post meta
            update_post_meta($post_id, '_answer_file', $upload);
        }
    }
}

wp_send_json($result);

【问题讨论】:

  • 非常方便,谢谢。开始附近有一个小错误 - 上面的 substr(ini_get('post_max_size'), -1) 应该是 substr(ini_get('post_max_size'), 0, -1)

标签: php ajax wordpress


【解决方案1】:

阅读并理解错误信息告诉你什么:

超过第 0 行 Unknown 中 XXXXX 字节的限制

错误在第 0 行报告,因为它在您的 PHP 代码执行之前被抛出。所以你不能改变接收 PHP 脚本中的行为。

正确的方法是检查数据的大小BEFORE you upload it(即在 Javascript 中)。但请注意:

  1. Javascript 报告单个文件的大小它们被编码 - Base64 编码增加了大约三分之一的开销,加上其他 POST 属性值和名称的空间。

  2. 为 post_max_size 配置的值是 PHP 接受的最大值。网络服务器(例如apache)将接受的最大值可能会更低。对于插件来说,也许最合适的解决方案是让管理员配置上限。

  3. 试图破坏您的安全的人可以轻松绕过 Javascript 中的任何检查

【讨论】:

  • 我会投票赞成,但您的回答除外,因为在前端检查文件大小是我考虑作为正确解决方案的唯一解决方案,只是想确认我已在后端完成。谢谢
  • 我不明白为什么人们会接受建议调整 php.ini 中的最大限制的答案。这根本不能解决它。因为这些总是可以超过的。假设将 post_max_size 调整为 100MB,如果另一个用户发布 200MB 怎么办?无论调整多少限制,问题总是会发生。更好的解决方案是首先验证请求的内容长度并根据需要继续执行脚本,比如是否停止上传。人们不想等待上传 200MB 的数据才发现它是无效的。 us2.php.net/manual/en/features.file-upload.post-method.php
  • @doncadavona:“更好的解决方案是首先验证请求的内容长度” - 当 PHP 直到文件上传完成后才开始执行时,您如何建议这样做?
  • @symcbean,我不确定。我也想知道。我想现在的问题是 PHP 是否支持它?在执行之前验证帖子大小,就像它如何支持每个帖子的文件一样?为什么或者为什么不?如果没有,我认为 PHP 至少应该在超过允许的最大值时停止上传。假设 PHP 接受
  • @doncadavona:webserver 选择何时将请求交给 PHP / 在 CGI 和 fast_cgi 的情况下,它必须缓冲整个请求。
【解决方案2】:

试试这个链接:http://code.tutsplus.com/tutorials/uploading-files-with-ajax--net-21077

在这个upload.php页面(上传文件的ajax的主要回调函数)你会得到$_FILES["images"]["size"]上传的图片大小

【讨论】:

  • 不,在这种情况下你甚至不会得到 $_POST 和 $_FILES 数据,这两个数组将为空
  • 你可以把代码粘贴到你写文件上传代码的地方
  • 用 AJAX 调用更新了,但我觉得没那么重要
  • 不是这个..文件上传代码写到哪个ajax发布的代码
猜你喜欢
  • 2011-09-10
  • 2020-12-04
  • 2016-08-21
  • 2012-07-29
  • 2012-10-14
  • 2017-03-12
  • 2017-08-24
  • 2019-11-19
相关资源
最近更新 更多