2016-03-02 203 views
4

美好的一天)我正在构建一个WordPress插件LMS,允许用户通过AJAX将他们完成的家庭作业文件附加到他们的答案中。一切正常,除了一个场景,当用户的文件超过允许的最大大小。在这种情况下我的AJAX调用返回的HTML具有以下警告:很好地处理“POST内容 - 字节长度超过了限制”警告

<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. 我发现this教程由安德鲁Curioso,并设法使从它的东西是这样的:

    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_jso n(errorsArray),它不会被执行)。

  1. 使用display_errors,error_reporting关闭显示错误。那么,这不是我需要的,因为它仍然不允许我继续使用脚本并创建自定义错误处理程序。什么样的建议,我不是在寻找手动编辑max_upload_size,max_post_size等作为手动编辑服务器上的文件是外挂程式理念

  2. 我WP_DEBUG设置为FALSE

。无论如何,即使您将最大上传大小设置为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); 
+0

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

回答

5

上传的图片的尺寸请务必阅读和了解什么错误消息告诉你:

超过XXXXX字节的限制在未知在线0

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

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

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

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

  3. 有人试图可以很容易地破坏你的安全绕过在Javascript

    任何检查
+0

我会upvote和除了你的答案,因为在前端检查文件大小是唯一的解决方案,我正在考虑作为适当的一个,只是想确认我在后端完成。谢谢 – markoffden

+1

我不明白为什么人们接受建议调整php.ini中的最大限制的答案。这根本不能解决它。因为这些都可以被超越。说调整post_max_size为100MB,如果另一个用户发布200MB呢?无论限制调整多少,问题总会发生。一个更好的解决方案将首先验证请求的内容长度,并根据需要继续执行脚本,例如停止上载或不上载。人们不希望等待上传200MB数据才能发现它无效。 http://us2.php.net/manual/en/features.file-upload.post-method.php – doncadavona

+0

@doncadavona:“一个更好的解决方案将首先验证请求的内容长度” - 你如何建议这样做当PHP直到文件上传完成后才开始执行? – symcbean

0

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

在此上传。PHP页面(这是阿贾克斯的,其上传该文件的主要回调函数),你会得到$_FILES["images"]["size"]

+0

不行,在这种情况下你甚至不会得到$ _POST和$ _FILES的数据,这两个数组将会是空的 – markoffden

+0

可以ü粘贴代码,你写的文件上传代码 –

+0

更新为AJAX调用, t认为它很重要 – markoffden

相关问题