<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/book.session.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'ru',
  ),
  'this' => 
  array (
    0 => 'session.upload-progress.php',
    1 => 'Отслеживание хода загрузки файлов через сессии',
    2 => 'Отслеживание хода загрузки файлов через сессии',
  ),
  'up' => 
  array (
    0 => 'book.session.php',
    1 => 'Сессии',
  ),
  'prev' => 
  array (
    0 => 'session.customhandler.php',
    1 => 'Пользовательские обработчики сессии',
  ),
  'next' => 
  array (
    0 => 'session.security.php',
    1 => 'Безопасность сессий',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ru',
    'path' => 'reference/session/upload-progress.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="session.upload-progress" class="chapter">
 <h1 class="title">Отслеживание хода загрузки файлов через сессии</h1>


 <p class="para">
  PHP умеет отслеживать ход загрузки отдельных файлов, если включить
  INI-директиву <a href="session.configuration.php#ini.session.upload-progress.enabled" class="link">session.upload_progress.enabled</a>.
  Эта информация не приносит пользы самому запросу на отправку файла,
  но во время загрузки файла приложение может отправить POST-запрос отдельной конечной точке, например
  через интерфейс <abbr>XHR</abbr>, чтобы проверить статус.
 </p>
 <p class="para">
  Ход загрузки будет доступен в суперглобальной переменной
  <var class="varname"><a href="reserved.variables.session.php" class="classname">$_SESSION</a></var> по мере загрузки файла,
  и при отправке POST-переменной с тем же именем, которое установили для INI-параметра
  <a href="session.configuration.php#ini.session.upload-progress.name" class="link">session.upload_progress.name</a>.
  Когда PHP обнаруживает такие POST-запросы, он заполняет
  в переменной <var class="varname"><a href="reserved.variables.session.php" class="classname">$_SESSION</a></var> массив, в котором ключом будет конкатенация
  значений опций
  <a href="session.configuration.php#ini.session.upload-progress.prefix" class="link">session.upload_progress.prefix</a>
  и
  <a href="session.configuration.php#ini.session.upload-progress.name" class="link">session.upload_progress.name</a>.
  Ключ обычно получают путём чтения значений этих директив, то есть:
  <div class="informalexample">
   <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />$key </span><span style="color: #007700">= </span><span style="color: #0000BB">ini_get</span><span style="color: #007700">(</span><span style="color: #DD0000">"session.upload_progress.prefix"</span><span style="color: #007700">) . </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #0000BB">ini_get</span><span style="color: #007700">(</span><span style="color: #DD0000">"session.upload_progress.name"</span><span style="color: #007700">)];<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$_SESSION</span><span style="color: #007700">[</span><span style="color: #0000BB">$key</span><span style="color: #007700">]);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </p>
 <p class="para">
  Разработчики <em>отменяют</em> текущую загрузку файла через установку
  для ключа <code class="literal">$_SESSION[$key][&quot;cancel_upload&quot;]</code> значения <strong><code><a href="reserved.constants.php#constant.true">true</a></code></strong>, когда требуется.
  При загрузке набора файлов в одном запросе этот способ отменит
  только текущую загрузку файла, которая уже началась, и загрузки в очереди,
  но не удалит загрузки, которые уже завершились.
  При отмене загрузки таким способом PHP установит элементу массива
  <var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES</a></var> с ключом <code class="literal">error</code>
  значение константы <strong><code><a href="filesystem.constants.php#constant.upload-err-extension">UPLOAD_ERR_EXTENSION</a></code></strong>.
 </p>
 <p class="para">
  Директивы <a href="session.configuration.php#ini.session.upload-progress.freq" class="link">session.upload_progress.freq</a>
  и <a href="session.configuration.php#ini.session.upload-progress.min-freq" class="link">session.upload_progress.min_freq</a>
  определяют, как часто требуется обновлять информацию о ходе загрузки.
  Накладные расходы на эту функцию не ощущаются при разумных значениях этих настроек.
 </p>
 <p class="para">
  <div class="example" id="example-1">
   <p><strong>Пример #1 Пример информации</strong></p>
   <div class="example-contents"><p>
    Пример структуры массива прогресса загрузки.
   </p></div>
   <div class="example-contents">
<div class="htmlcode"><pre class="htmlcode">&lt;form action=&quot;upload.php&quot; method=&quot;POST&quot; enctype=&quot;multipart/form-data&quot;&gt;
    &lt;input type=&quot;hidden&quot; name=&quot;&lt;?php echo ini_get(&quot;session.upload_progress.name&quot;); ?&gt;&quot; value=&quot;123&quot; /&gt;
    &lt;input type=&quot;file&quot; name=&quot;file1&quot; /&gt;
    &lt;input type=&quot;file&quot; name=&quot;file2&quot; /&gt;
    &lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;</pre>
</div>
   </div>

   <div class="example-contents"><p>
    Данные, которых хранятся в сессии, будут выглядеть вот так:
   </p></div>
   <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">&lt;?</span><span style="color: #0000BB">php<br /><br />$_SESSION</span><span style="color: #007700">[</span><span style="color: #DD0000">"upload_progress_123"</span><span style="color: #007700">] = array(<br />    </span><span style="color: #DD0000">"start_time" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">1234567890</span><span style="color: #007700">,   </span><span style="color: #FF8000">// Время начала запроса<br />    </span><span style="color: #DD0000">"content_length" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">57343257</span><span style="color: #007700">, </span><span style="color: #FF8000">// Длина содержимого POST-запроса<br />    </span><span style="color: #DD0000">"bytes_processed" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">453489</span><span style="color: #007700">,  </span><span style="color: #FF8000">// Количество байтов, которые получил и обработал запрос<br />    </span><span style="color: #DD0000">"done" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">false</span><span style="color: #007700">,              </span><span style="color: #FF8000">// После завершения обработки POST-запроса значение изменится на true,<br />                                  // независимо от того, успешно или нет завершилась обработка<br />    </span><span style="color: #DD0000">"files" </span><span style="color: #007700">=&gt; array(<br />        </span><span style="color: #0000BB">0 </span><span style="color: #007700">=&gt; array(<br />            </span><span style="color: #DD0000">"field_name" </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">"file1"</span><span style="color: #007700">,       </span><span style="color: #FF8000">// Значение атрибута name поля &lt;input/&gt;<br />            // Следующие 3 элемента соответствуют элементам суперглобального массива $_FILES<br />            </span><span style="color: #DD0000">"name" </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">"foo.avi"</span><span style="color: #007700">,<br />            </span><span style="color: #DD0000">"tmp_name" </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">"/tmp/phpxxxxxx"</span><span style="color: #007700">,<br />            </span><span style="color: #DD0000">"error" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">0</span><span style="color: #007700">,<br />            </span><span style="color: #DD0000">"done" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">true</span><span style="color: #007700">,                </span><span style="color: #FF8000">// Элемент получает значение true, когда обработчик POST-запроса<br />                                           // закончил обработку файла<br />            </span><span style="color: #DD0000">"start_time" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">1234567890</span><span style="color: #007700">,    </span><span style="color: #FF8000">// Время начала обработки файла<br />            </span><span style="color: #DD0000">"bytes_processed" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">57343250</span><span style="color: #007700">, </span><span style="color: #FF8000">// Количество байтов, которые запрос получил и обработал для файла<br />        </span><span style="color: #007700">),<br />        </span><span style="color: #FF8000">// Ещё один файл, загрузка которого ещё не закончилась в том же запросе<br />        </span><span style="color: #0000BB">1 </span><span style="color: #007700">=&gt; array(<br />            </span><span style="color: #DD0000">"field_name" </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">"file2"</span><span style="color: #007700">,<br />            </span><span style="color: #DD0000">"name" </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">"bar.avi"</span><span style="color: #007700">,<br />            </span><span style="color: #DD0000">"tmp_name" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">NULL</span><span style="color: #007700">,<br />            </span><span style="color: #DD0000">"error" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">0</span><span style="color: #007700">,<br />            </span><span style="color: #DD0000">"done" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">false</span><span style="color: #007700">,<br />            </span><span style="color: #DD0000">"start_time" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">1234567899</span><span style="color: #007700">,<br />            </span><span style="color: #DD0000">"bytes_processed" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">54554</span><span style="color: #007700">,<br />        ),<br />    )<br />);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </p>
 <div class="warning"><strong class="warning">Внимание</strong>
  <p class="para">
   Для правильной работы требуется отключить буферизацию запросов веб-сервера,
   иначе PHP увидит загрузку файла только после полной загрузки.
   Серверы наподобие Nginx буферизуют большие запросы.
  </p>
 </div>
 <div class="caution"><strong class="caution">Предостережение</strong>
  <p class="para">
   Информация о ходе загрузки записывается в сессию перед выполнением
   скриптов. Поэтому PHP начнёт сессию без информации о ходе загрузки,
   если изменить название сессии функцией
   <span class="function"><a href="function.ini-set.php" class="function">ini_set()</a></span> или <span class="function"><a href="function.session-name.php" class="function">session_name()</a></span>.
  </p>
 </div>
</div>
<?php manual_footer($setup); ?>