Как определить, загрузил ли пользователь файл больше, чем post_max_size? - PullRequest
10 голосов
/ 31 мая 2011

Как мне поступить с обработкой http-загрузок, которые в разумной степени превышают post_max_size?

В моей конфигурации post_max_size на несколько МБ больше, чем upload_max_filesize Проблемы, с которыми я сталкиваюсь,:
Если пользователь загружает файл, размер которого превышает post_max_size

  • Массив _POST пуст
  • Массив _FILES пуст, и, конечно, никаких кодов ошибок в нем нет,
  • Никакой другой информации о том, что это за форма сообщения, доступно через эти средства.

Часть проблемы заключается в том, что принимающий скрипт выполняет различные действия в зависимости от содержимого POST,

У меня есть доступ к переменным _SERVER, и я могу получить подсказки о том, что произошло, то есть CONTENT_TYPE, CONTENT_LENGTH и REQUEST_METHOD.Тем не менее, кажется очень проблематичным делать предположения на основе этого содержимого.

MEMORY_LIMIT (установлено в 10 раз больше соответствующих размеров) и Apaches LimitRequestBody (установлено на неограниченное количество), как считается, не виноваты.

В нынешнем виде мне трудно даже давать какие-либо значимые сообщения пользователю.

Есть ли способ сохранить некоторые данные формы, чтобы лучше понять, что пошло не так?Я очень не хочу уходить от php.

Ответы [ 6 ]

9 голосов
/ 31 мая 2011

Для простого исправления, которое не требовало бы изменений на стороне сервера, я бы использовал HTML5 File API, чтобы проверить размер файла перед загрузкой.Если он превышает известный лимит, отмените загрузку.Я полагаю, что-то вроде этого будет работать:

function on_submit()
{
  if (document.getElementById("upload").files[0].size > 666)
  {
    alert("File is too big.");
    return false;
  }

  return true;
}

<form onsubmit="return on_submit()">
<input id="upload" type="file" />
</form>

Очевидно, что это всего лишь скелет примера, и не каждый браузер поддерживает это.Но это не мешало бы использовать это, так как это могло бы быть реализовано таким образом, что оно изящно превращается в ничто для старых браузеров.

Конечно, это не решает проблему, но это по крайней мереСделайте так, чтобы количество ваших пользователей было довольным с минимальными усилиями.(И им даже не придется ждать сбоя загрузки.)

-

Кроме того, может помочь проверка $_SERVER['CONTENT_LENGTH'] против размера сообщения и данных файла.обнаружить, если что-то не удалось.Я думаю, что при возникновении ошибки она будет отлична от нуля, тогда как $_POST и $_FILES будут пустыми.

3 голосов
/ 31 мая 2011

Согласно документации PHP :

Если размер данных публикации больше, чем post_max_size, суперглобальные переменные $ _POST и $ _FILES пусты.Это можно отследить различными способами, например, передав переменную $ _GET скрипту, обрабатывающему данные, т.е., а затем проверяя, установлено ли $ _GET ['обработано'].

Если вам нужно увеличить предел для конкретного сценария, вы можете попробовать ini_set ('post-max-size ', $ size_needed) ;.Я не уверен, может ли это быть переопределено в скрипте;этот предел, вероятно, существует, чтобы специально удерживать вас от того, что вы пытаетесь сделать.

1 голос
/ 22 августа 2013

Вы можете решить эту проблему на стороне сервера, не прибегая к строке запроса.Просто сравните параметр * post_max_size * с ожидаемой длиной содержимого запроса.Следующий код показывает, как это делает Кохана.

public static function post_max_size_exceeded()
{
    // Make sure the request method is POST
    if (Request::$initial->method() !== HTTP_Request::POST)
        return FALSE;

    // Get the post_max_size in bytes
    $max_bytes = Num::bytes(ini_get('post_max_size'));

    // Error occurred if method is POST, and content length is too long
    return (Arr::get($_SERVER, 'CONTENT_LENGTH') > $max_bytes);
}
1 голос
/ 16 августа 2013

Мне понравился ответ @Matthew, но мне нужна была версия, которая проверяла наличие нескольких загружаемых файлов.

Это было мое решение:

function checkAttachmentsSize() {
    var total = 0;
    var count = 0;

    jQuery('input[type="file"]').each(
        function() {
            if (typeof this.files[0] != 'undefined') {
                total+= this.files[0].size;
                count++;
            }
        }   
    );

    var word = (count > 1) ? 's are' : ' is';
    if (total > (uploadMax * 1000 * 1000)) {
        alert("The attachment file" + word + " too large to upload.");
        return false;
    }

    return true;
}

И, для полноты, вот привязкаФункция к отправляемой форме:

jQuery(function($) {
    $("form").submit(
        function() {
            return checkAttachmentsSize();
        }   
    });
);

ПРИМЕЧАНИЕ:
uploadMax - это переменная, которую я установил через php после вычисления максимального размера допустимой загрузки.

0 голосов
/ 31 мая 2011

Если ваша форма загрузки не имеет полей, отличных от поля ввода файла, то $ _POST должен быть пустым - файлы обрабатываются исключительно через $ _FILES. Очень странно, что $ _FILES будет пустым, если размер сообщения будет превышен - обработчики загрузки имеют определенный код ошибки (1 / UPLOAD_ERR_INI_SIZE ), чтобы сообщить о таком условии. Также убедитесь, что memory_limit больше, чем upload_max_filesize.

Возможно, ваш веб-сервер также блокирует загрузку, что происходит до вызова PHP. На Apache он контролируется LimitRequestBody.

0 голосов
/ 31 мая 2011

Возможно, вам придется вернуться к чему-то, что использует вспышку / серебристый свет и т. Д., Например: http://www.plupload.com/

Или посмотрите на решение на основе Java ...

По существу что-то, что разбивает загрузку на более управляемые (и возобновляемые) куски, а затем повторно собирает их на стороне сервера.

...