Relação entre memory_limit de php, upload_max_filesize e post_max_filesize

Linha inferior :
Preciso me preocupar em configurar post_max_filesize >> memory_limit ?

Detalhes :
Esta resposta sugere que os arquivos carregados não precisam se encheckboxr no memory_limit do php. Os php docs sugerem que a publicação inteira deve caber dentro do limite de memory do php.

Acho que os docs são surpreendentes e espero que alguém possa elaborar. Por exemplo, execute as seguintes configurações de php:

 ; config A memory_limit = 50M upload_max_filesize = 100M post_max_filesize = 1000M max_file_uploads = 10 

e

 ; config B memory_limit = 50M upload_max_filesize = 10M post_max_filesize = 1000M max_file_uploads = 100 

Com essas configurações, espero poder:

  • Carregar arquivos 10x100mb para o servidor A ,
  • e arquivos de 100x10mb para o servidor B.

Eu também esperaria isso:

  • Trabalhar com qualquer um dos 10 arquivos carregados para o servidor A é um problema (100Ms de arquivo em um saco de 50M …).
  • Trabalhar com qualquer um dos 100 arquivos carregados no servidor B está bem (10 <50).

Ao experimentar com números menos redondos, mas equivalentemente relacionados, achei que essas expectativas são verdadeiras.

Esta experiência me levaria a dizer que “geralmente o memory_limit deve ser maior que o upload_max_filesize “; Em vez disso, os php docs dizem:

Em geral, memory_limit deve ser maior do que post_max_size .

Por que e o que acontece se não for?

Quando meu código php é executado, não vejo nenhuma evidência de que todos os arquivos publicados estão na memory. Parece-me que tudo o que tenho é uma matriz $ _FILES de caminhos para arquivos encontrados exclusivamente no disco. O php está segurando todo o post na memory em algum ponto antes da minha capacidade de introspecção do meio ambiente? Preciso me preocupar em configurar post_max_filesize >> memory_limit ?

A parte, de lado:
Violar a regra do manual não resulta em um servidor grosseiramente quebrado (w / php5.3 apache2.2 debian 6).

O PHP aceita arquivos carregados que são individualmente menores que upload_max_filesize e, em conjunto, levam menos de bytes de post_max_size . A documentação do PHP está errada em relação ao memory_limit que não precisa manter o conteúdo do arquivo postado.

A configuração a seguir funciona com o módulo Apache2 e CGI, e aceita arquivos menores que 1G.

  upload_max_filesize = 1G post_max_size = 1G memory_limit = 32M 

Preciso me preocupar em configurar post_max_filesize >> memory_limit?

Somente se você planeja ler um arquivo inteiro na memory e o arquivo que você lê é maior do que o espaço que você atribuiu ao PHP (ou seja, memory_limit ), caso em que você ficará sem memory.

Minha própria experiência pessoal é que você DEVE ter um memory_limit maior do que post_max_size e upload_max_size.

O post_max_size refere-se à totalidade dos dados POSTed. Isso inclui todos os campos de formulário que podem ter sido incluídos no próprio arquivo. O upload_max_size é o maior tamanho permitido que um arquivo pode estar dentro desse upload.

Por exemplo. com um post_max_size de 10mb e um upload_max_size de 1mb, você pode carregar 9 arquivos, cada um de tamanho de 1mb, por que 9 arquivos? porque parte dos dados POST são os metadados do arquivo – nome do arquivo, tipo de mime, tamanho do arquivo, etc … Isso ocupa algum espaço, então seus 9 arquivos realmente ocuparão 9.01 megabytes ou assim. A restituição de 0,99 é muito pequena para outro arquivo, então você não pode carregar esse 10, mesmo que ele se encaixe no limite upload_max_size.

Quanto ao memory_limit, não só você tem que ter espaço suficiente para os arquivos que foram carregados, você deve lembrar que esse limite se aplica ao script como um todo. Um memory_limit de 10mb permitiria que apenas um arquivo de 9 megabytes fosse carregado, porque o próprio PHP e todos os códigos e bibliotecas associados irão sugar (digamos) 1 megabyte já.

Mesmo que os arquivos não sejam mantidos em memory – eles são despejados para os arquivos temporários o mais rápido possível, eles são passados ​​para o PHP a partir do Apache via STDIN. O PHP tem que ler os arquivos desse stream e copiá-los para os arquivos temporários que você usa na seção ['tmp_name'] da matriz $ _FILES.

Por qualquer motivo, o PHP parece estar basicamente fazendo “file_get_contents ()” e slurping os arquivos em massa, em vez de fazer uma cópia de tipo streaming. Por isso, exige um memory_limit que exceda o maior tamanho de arquivo permitido.