Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > ошибка 413 Request Entity Too Large при ajax


Автор: mstdmstd 28.3.2016, 08:28
Всем привет,
Есть необходимость загрузить картинку в строковом представлении через ajax - запрос. Делаю: 
Код

                        alert( "capture_image typeof data::"+ (typeof data) +"   data.length::"+data.length+"   data::"+data )
                        jQuery.ajax({
                            url: '<?php echo site_url( "dashboard/save_template_full_image" ) ?>',
                            type: 'POST',
                            dataType: "json",
                            data: {
                        <?php echo $this->security->get_csrf_token_name(); ?>:"<?php echo $this->security->get_csrf_hash(); ?>",
                            id:            _templateID,
                            image_capture:        data
                    },
                    success: function(result) {


алерт в самой первой строке выводит 
Код

capture_image typeof data::string   data.length::17449558   data::data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAACbAAAAbUCAYAAAAkT6


И после паузы получаю ошибку 413 Request Entity Too Large...
Длина строки это ~ 16 МБ

Открываю и смотрю etc/php.ini :
Код


; Rename this file to php.ini and uncomment or add directives.
; For a complete list of valid directives, visit:
;  http://us2.php.net/manual/en/ini.php

[PHP]
; We highly recommend that you leave this options enabled
cgi.fix_pathinfo=1

apc.max_file_size = 1024M
;512M
apc.shm_size = 1024M
;512M
max_execution_time = 900
;300
memory_limit = 1024M
;512M
; post_max_size = 256M
upload_max_filesize = 1024M
;512M

; Increase maximum post size
post_max_size = 1024M
;; 512M

;error_reporting = E_ALL &amp; ~E_DEPRECATED &amp; ~E_NOTICE

; Increase execution time
;max_execution_time = 300

; pull in EGPCS [Environment, GET, POST, Cookie, Server] variables as globals
;register_globals = true

; For performance reasons, (mt) does not load all of the modules that are available
; into PHP. You may uncomment any one of the following "extension" lines to enable
; the desired module

; Salblotron XSLT
;extension=xslt.so

; save in local tmp
session.save_path=/home/181213/data/tmp

allow_url_fopen = 1

output_buffering = on
default_socket_timeout = 300



В phpinfo я вижу :

PHP Version 5.5.21
...
Код

memory_limit    1024M    1024M

post_max_size    1024M    1024M

upload_max_filesize    1024M    1024M

max_execution_time    900    900 

upload_max_filesize    1024M    1024M


Не подскажите в чем проблема и как ее побороть? Файл, который я пытаюсь записать довольно большой, но явно меньше параметров в конфе.

Или это ограничения d ajax-запросе ?
Гуглом я не нашел есть ли ограничения в размере для ajax-запроса...

Автор: ksnk 28.3.2016, 11:08
В гугле на строку `413 Request Entity Too Large` выводит http://ruhighload.com/post/%D0%9E%D1%88%D0%B8%D0%B1%D0%BA%D0%B0+413+Request+Entity+Too+Large
Не оно?

Загружать файлы, вообще говоря, проще и правильнее с помощью объекта  formData

Автор: mstdmstd 28.3.2016, 13:51
formData это пример отсюда ?
http://stackoverflow.com/questions/6974684/how-to-send-formdata-objects-with-ajax-requests-in-jquery

Код

ar fd = new FormData();    
fd.append( 'file', input.files[0] );

$.ajax({
  url: 'http://example.com/script.php',
  data: fd,
  processData: false,
  contentType: false,
  type: 'POST',
  success: function(data){
    alert(data);
  }
});


FormData - не нужно подключть более никаких библитотек и input.files[0]  - это текст моей картинки и  'http://example.com/script.php' - скрипт принимающий файл?

Автор: ksnk 28.3.2016, 13:59
Да, это он. 
Единственное ограничение - нужен относительно современный броузер. IE10 минимум...

Добавлено через 5 минут и 8 секунд
Возможно, вот это пригодится http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata

Автор: mstdmstd 29.3.2016, 10:09
Спасибо!
Пообщался с сапортом, там ограничения на post_max_size = 24M, хотя у меня и меньшие файлы выдают ошибку,
в независимости что написано в php.ini.
И решил переделать загрузку сабмитом формы без аджакса - и вопрос, а есть ли удобные утилиты для загрузки больший файлов наподобе FormData, но при сабмите формы?

Автор: ksnk 29.3.2016, 10:35
Цитата(ksnk @  28.3.2016,  11:08 Найти цитируемый пост)
В гугле на строку `413 Request Entity Too Large` выводит http://ruhighload.com/post/%D0%9E%D1%88%D0...ntity+Too+Large
Не оно?

По ссылке удалось почитать?
413 ошибку выдает не php, а сервер. Параметры в php.ini не успевают сыграть.
Какой сервер-то? nginx - смотреть параметр 
 client_max_body_size 32m

Автор: mstdmstd 29.3.2016, 12:46
Да ссылку я посмотрел
Саппорт мне ответил:
Код

The max allowed on the Grid are as follows:
memory_limit = 99M
max_execution_time = 300
upload_max_filesize = 20M
post_max_size = 24M
pmGoing over these values will truncate them to the capped amount but you should still be within these with a 16MB file
Though if I recall correctly over 10MB do tend to get a little unstable and timeout or drop connections

Упоминания про параметр client_max_body_size в Grid(это такой аналог cPanel) и в phpinfo я не нашел 
Сапорту я писал про этот параметр но они ответили параметрами выше и видимо эти 24M и есть client_max_body_size?


И решил переделать загрузку сабмитом формы без аджакса - и вопрос, а есть ли удобные утилиты для загрузки больший файлов наподобе FormData, но при сабмите формы? 

Автор: ksnk 29.3.2016, 13:02
Саппорт ответил цитатой из php.ini.

http://seyferseed.ru/ru/php/bol-shoj-razmer-post-zaprosa-v-php.html

Цитата

Если используется apache2, то в /etc/apache2/apache.conf:
LimitRequestFieldsize – размер поля
LimitRequestBody – размер всего запроса

Автор: mstdmstd 29.3.2016, 13:23
есть доступ только к php.ini

Доступа к apache.conf - нет

И ответьте, пожалуйста, на мой вопрос: И решил переделать загрузку сабмитом формы без аджакса - и вопрос, а есть ли удобные утилиты для загрузки больший файлов наподобе FormData, но при сабмите формы? 


Автор: ksnk 29.3.2016, 13:46
mstdmstd, Да, `jquery file upload` в строке гугла. Например https://plugins.jquery.com/blueimp-file-upload/ 

Автор: mstdmstd 29.3.2016, 22:45
C Query File Upload - я работал - но не въеду как это поможет с загрузкой больших файлов ?
Разве на этот загрузчик не действуют те же ограничения в максимальном размере post-запроса?

Автор: ksnk 29.3.2016, 22:59
Если нет намерений разбираться с настройками сервера, то остается только уменьшить загружаемый образ. FormData позволит не увеличивать размер POST лишними перекодировками.
Если нет желания разбираться с FormData, то готовый плагин сделает все сам.

Автор: whatisnot 30.3.2016, 17:18
Цитата(mstdmstd @  29.3.2016,  22:45 Найти цитируемый пост)
C Query File Upload - я работал - но не въеду как это поможет с загрузкой больших файлов ?


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

Автор: ksnk 30.3.2016, 17:24
whatisnot, Каким образом FileReader поможет загрузить файл на сервер? 

Автор: whatisnot 31.3.2016, 02:17
Цитата(ksnk @  30.3.2016,  17:24 Найти цитируемый пост)
Каким образом FileReader поможет загрузить файл на сервер?


Для этого достаточно прочесть о методах данного объекта. Все просто - большие файлы разбиваются на части и передаются на сервер частями.

Автор: mstdmstd 31.3.2016, 16:18
Отправлять в base64, это в три раза больший объем от исходного
Значит мне декадировку надо делать на клиенте и отправлять в сабмит уже перекодированную строку
Для этого можно использовать функцию decode64 отсюда  http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
Судя по описанию это кроссбаузерное решение...
Это уменьшает файл отправки - но не факт что будет достаточно Смотрим  FileReader( https://developer.mozilla.org/en/docs/Web/API/FileReader ):
Цитата



File objects may be obtained from a FileList object returned as a result of a user selecting files using the <input> element, from a drag and drop operation's DataTransfer object, or from the mozGetAsFile() API on an HTMLCanvasElement.

А у меня файл в виде 64 битной строки, которую я могу декодировать. 
А вот методов для записи я не вижу. Если whatisnot, ничего не напутал, то, плиз, ткните, что за методы?

Автор: ksnk 31.3.2016, 18:40
Откуда взялась такая строка? Может чуть ранее по коду есть более удобный вид?

Можно строку преобразовать в объект blob, который http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata. Пример, правда, с formData, но и FileReader должен такое открывать.

Автор: whatisnot 31.3.2016, 19:05
Цитата(mstdmstd @  31.3.2016,  16:18 Найти цитируемый пост)
Если whatisnot, ничего не напутал, то, плиз, ткните, что за методы?


Методов для этого придется использовать много и не только FileReader. Ну напрягите гугл, об этом (загрузка файлов на сервер частями) написано так много, вот с лету первое попавшееся -http://www.codenet.ru/webmast/js/html5-ajax-partial-upload/, что переписывать уже описанное... Есть на Хабре статьи по этому поводу, и решений не одно. Вы родите что либо свое из познанного, а уже о своих ошибках, если будут допущены, спрашивайте.   

Автор: mstdmstd 1.4.2016, 09:08
Спасибо, буду пробовать
Пока что я хочу 64-битной строку декодировать на клиенте и отправить сабмитом формы
Возможно уменьшив данные в сабмит и не будет ошибки из-за большого обьема данных...
Делаю 
Код

       var data = original_canvas.toDataURL(); // Источник данных fabrics js
       alert("+++original_frnt_img_val::"+var_dump(data) );   // алер выводит   +++original_frnt_img_val::data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAACbAAAAbUCAYA ...



      var decoded_data= data.replace(/data\:image\/png\;base64\,/g, "")  // Убираем заголовок data:image/png;base64,
      alert( "decoded_data::"+var_dump(decoded_data) )         //  выводит decoded_data::iVBORw0KGgoAAAANSUhEUgAACbAAAAbUCAYAAAAkT...
      var decoded_data= decode64(decoded_data)                   // декодируем
      alert( "decoded_data::"+var_dump(decoded_data) )         //  выводит http://imgur.com/QTM9o6q


       alert( "ZZZ::"+var_dump(  jQuery('#original_frnt_img_val').val()  ) ) // Выводит ту же строку что и выше
       var theForm = jQuery("#form_save_template_full_image");
       theForm.submit(); // Сабмитим форму

       
       
       Форма сабмититься и файл записывается на диск функцией file_put_contents без перекодировки и изменений но при попытке прочитать его получаю
Код

       "Loading capture.png" failed

       
       И открыв этот файл в текстовом редакторе я вижу http://i.imgur.com/luLBkhj.png
       Сравнивая этот файл с другими png-файлами  в текстовом редакторе вижу что они не похожи


Функция decode64 взята отсюда http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
Я пробовал использовать atob вместо decode64 и тот же результат

Изначально я отправлял 64-данные и на сервере делал перекодировку перед записью в файл: 
Код

$upload_front = file_put_contents( $capture_dest_filename , base64_decode( preg_replace("/data:image\/png;base64,/", '', $original_frnt_img_val ) )  );



Автор: ksnk 1.4.2016, 11:05
mstdmstd, Я понимаю, конечно, желание обойтись малой кровью, но FormData был придуман совсем не от того, что кому то не хотелось использовать стандартную форму. Причина в том, что стандартной формой можно сделать далеко не все. В частности, послать файл довольно сложно. А в "обычном" для формы виде - практически невозможно.
Можно посмотреть на мои ссылки и попытаться воспользоваться этим объектом. Потом, когда размер загружаемого файла опять упрётся в нежелание разбираться с настройками сервера, можно почитать про FileReader, поискать примеры его использования для загрузки файлов по кусочкам. 
Если нужен результат, а не личный опыт - проще и разумнее воспользоваться плагином. 

Автор: mstdmstd 5.4.2016, 13:36
Спасибо за подсказки!
Сделал с небольшими изменениями как описано здесь https://habrahabr.ru/company/Techart/blog/100189/.
Как я понимаю, решение кроссбраузерно, пока у браузера клиента хватит памяти...
Локально и на сервре работает, хотя судя по кометариям во многих случаях этого недостаточно...

Автор: ksnk 5.4.2016, 14:09
Нужно понимать, что пока клиент не загрузит все данные, его броузер(страница) будет заблокирован. Можно посмотреть на комментарии по ссылке на хабре
Цитата

 0lympian  26 июля 2010 в 21:47  0     
Кстати… вместо отключения асинхронности лучше бы отправляли номер чанка и собирали при получении последнего
  sunnybear  26 июля 2010 в 22:42    0     
угу, серверная часть при этом не сложнее: открываем файл, перемещаемся на позицию X, пишем очередной чанк. Ну и можно заранее создавать нужный по размеру файл, забитый нулями.

Ну и тот факт, что статья написана 6 лет назад говорит о том, что плагины могли бы оказаться уже написаными.
https://habrahabr.ru/post/154097/ - более новая статья, с примерами работы с FileReader и FormData


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)