Por que $ _FILES estaria vazio ao fazer upload de arquivos para PHP?

145

Eu tenho o WampServer 2 instalado no meu computador com Windows 7. Estou usando o Apache 2.2.11 e o PHP 5.2.11. Quando tento fazer upload de qualquer arquivo de um formulário, ele parece carregar, mas no PHP, a $_FILESmatriz está vazia. Não há arquivo na c:\wamp\tmppasta. Eu configurei php.inipara permitir uploads de arquivos e tal. A tmppasta possui privilégios de leitura / gravação para o usuário atual. Estou perplexo.

HTML:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <form enctype="multipart/form-data" action="vanilla-upload.php" method="POST">
        Choose a file to upload: <input name="uploadedfile" type="file" /><br />
        <input type="submit" value="Upload File" />
    </form>
</body>
</html>

PHP:

<?php
echo 'file count=', count($_FILES),"\n";
var_dump($_FILES);
echo "\n";
?>
elmonty
fonte
2
Você verificou os logs de erro?
Byron Whitlock
Tenho certeza de que há algo estúpido que você está ignorando. Por exemplo, você tem certeza de ter o código vanilla-upload.php?
Luca Matteis
Ha, eu estava tendo o mesmo problema. Verifiquei os logs de erro e ele dizia que estava sendo carregado um arquivo que excedia o tamanho máximo permitido.
precisa saber é o seguinte

Respostas:

493

Aqui está uma lista de verificação para upload de arquivos em PHP:

  1. Verifique o php.ini para:
    file_uploads = On
    post_max_size = 100M
    upload_max_filesize = 100M

    • Você pode precisar usar .htaccessou .user.inise estiver em hospedagem compartilhada e não tiver acesso php.ini.
    • Certifique-se de editar o arquivo ini correto - use a phpinfo()função para verificar se suas configurações estão realmente sendo aplicadas.
    • Também certifique-se que você não cometer erros de ortografia os tamanhos - deve ser 100M não 100MB .
  2. Verifique se sua <form>tag possui o enctype="multipart/form-data"atributo Nenhuma outra tag funcionará, ela deve ser sua tag FORM. Verifique novamente se está escrito corretamente . Verifique novamente se os dados de várias partes / formulário estão cercados por CITAÇÕES Retas, não por aspas inteligentes coladas no Word OU em um blog de site (o WordPress converte aspas retas em aspas angulares!). Se você tiver vários formulários na página, verifique se ambos têm esse atributo. Digite-os manualmente ou tente aspas simples e retas digitadas manualmente.

  3. Verifique se você não possui dois campos de arquivo de entrada com o mesmo nameatributo. Se você precisar oferecer suporte a vários, coloque colchetes no final do nome:

    <input type="file" name="files[]">
    <input type="file" name="files[]">
  4. Verifique se os diretórios tmp e upload têm as permissões corretas de leitura e gravação definidas. A pasta de upload temporário é especificada nas configurações do PHP como upload_tmp_dir.

  5. Verifique se o destino do arquivo e os diretórios tmp / upload não possuem espaços.

  6. Verifique se todas <form>as páginas da sua página têm </form>tags fechadas.

  7. Verifique se a sua etiqueta FORM possui method="POST". As solicitações GET não oferecem suporte a uploads com várias partes / dados de formulário.

  8. Verifique se a tag de entrada do arquivo possui um atributo NAME. Um atributo de ID NÃO é suficiente! Os atributos de ID são para uso no DOM, não para cargas POST.

  9. Verifique se você não está usando Javascript para desativar seu <input type="file">campo no envio

  10. Verifique se você não está aninhando formulários como <form><form></form></form>

  11. Verifique sua estrutura HTML para tags inválidas / sobrepostas, como <div><form></div></form>

  12. Verifique também se o arquivo que você está carregando não possui caracteres não alfanuméricos.

  13. Uma vez, passei horas tentando descobrir por que isso estava acontecendo comigo de repente. Aconteceu que eu havia modificado algumas das configurações do PHP .htaccess, e uma delas (ainda não tinha certeza de qual ainda estava) estava causando falha no upload e $_FILESvazio.

  14. Você pode tentar evitar sublinhados ( _) no name=""atributo da <input>tag

  15. Tente fazer upload de arquivos muito pequenos para diminuir se é um problema de tamanho de arquivo.

  16. Verifique o espaço em disco disponível. Embora muito raro, é mencionado neste comentário da página do Manual do PHP :

    Se a matriz $ _FILES repentinamente ficar misteriosamente vazia, mesmo que seu formulário pareça correto, verifique o espaço em disco disponível para sua partição de pasta temporária. Na minha instalação, todos os uploads de arquivos falharam sem aviso. Depois de muito ranger de dentes, tentei liberar espaço adicional, após o qual os uploads de arquivos subitamente funcionaram novamente.

  17. Verifique se você não está enviando o formulário através de uma solicitação AJAX POST, em vez de uma solicitação POST normal que faz com que uma página seja recarregada. Analisei todos os pontos da lista acima e finalmente descobri que o motivo pelo qual minha variável $ _FILES estava vazia era porque eu estava enviando o formulário usando uma solicitação AJAX POST. Eu sei que também existem métodos para fazer upload de arquivos usando ajax, mas esse pode ser um motivo válido para a matriz $ _FILES estar vazia.

Fonte para alguns desses pontos:
http://getluky.net/2004/10/04/apachephp-_files-array-mysteriously-empty/

shamittomar
fonte
12
Talvez a resposta "aceita" tenha resolvido a postagem original, mas essa foi a que achei mais útil. Em caso de dúvida, observe a fonte como vista pelo navegador. Ao marcar cada item desta lista e rastrear para trás, encontrei meu erro em um local inesperado. Se você está enfrentando um problema semelhante, acredite, provavelmente não é um bug no Apache. ;)
quickthyme
3
Verifique também se o elemento do formulário que contém a entrada do arquivo NÃO é filho de outro elemento do formulário. por exemplo<form><form><input type="file"></form></form>
sudee 14/08
3
Uau! Obrigado por esta lista. meu problema era # 2. eu estava chamando $('#my-form')[0].reset();no manipulador de envio.
Gavin
2
obrigado. no meu caso número 7. enctype = "multipart / form-data" foi o culpado.
Thupten
3
Cara, você é um salva-vidas. Passo horas tentando descobrir isso (2) foi o meu problema ... Obrigado!
Mike Q
74

No que diz respeito ao HTML, você parece ter configurado essa parte corretamente. Você já tem o enctype="multipart/form-data"que é muito importante ter no formulário.

Quanto à sua php.iniconfiguração, às vezes nos sistemas php.iniexistem vários arquivos. Certifique-se de editar o correto. Sei que você disse que configurou seu php.iniarquivo para fazer upload de arquivos, mas você também definiu upload_max_filesizee post_max_sizeé maior que o arquivo que está tentando enviar? Então você deve ter:

file_uploads = On; sounds like you already did this
post_max_size = 8M; change this higher if needed
upload_max_filesize = 8M; change this higher if needed

O seu diretório: "c:\wamp\tmp"possui permissões de leitura e gravação? Você se lembrou de reiniciar o Apache depois de fazer as php.inialterações?


Brian
fonte
4
+1: Para reiniciar a dica do servidor Apache. Muitos usuários do Windows esquecem isso.
Shamittomar 27/08/10
36

É importante adicionar enctype="multipart/form-data"ao seu formulário, exemplo

<form action="upload.php" method="post" enctype="multipart/form-data">
    Select image to upload:
    <input type="file" name="fileToUpload" id="fileToUpload">
    <input type="submit" value="Upload Image" name="submit">
</form>
meda
fonte
14

Obrigado a todos pelas várias respostas abrangentes. Tudo isso é muito útil. A resposta acabou sendo algo muito estranho. Acontece que o PHP 5.2.11 não gosta do seguinte:

post_max_size = 2G

ou

post_max_size = 2048M

Se eu mudar para 2047M, o upload funcionará.

elmonty
fonte
17
Observe que esse valor alto é uma vulnerabilidade a ataques de falta de espaço / ddos. Basta adicionar isso para que as pessoas saibam que é demais quando tentam copiar e colar sua solução. De qualquer forma, 2 shows exigiriam um tempo de upload muito longo.
Manuel Arwed Schmidt
Não é muito grande mais. Temos clientes que fazem upload de arquivos na faixa 1-3G com bastante regularidade. Como eles estão carregando arquivos em seus próprios servidores e são servidores na lista de permissões de IP, a troca é bastante normal e apenas uma maneira de permitir que um cliente use seu equipamento da maneira que ele deseja. Eles pagam as contas, sem riscos de segurança envolvidos, sem problemas.
TheSatinKnight
8

Eu tenho o mesmo problema procurando 2 horas, é muito simples verificarmos primeiro a configuração do servidor.

Exemplo:

echo $upload_max_size = ini_get('upload_max_filesize');  
echo $post_max_size=ini_get('post_max_size');   

qualquer tipo de tamanho de arquivo é :20mb, mas o nosso upload_max_sizeestá acima, 20mbmas o array é null. A resposta é a nossa post_max_sizedeve ser maior que upload_max_filesize

post_max_size = 750M  
upload_max_filesize = 750M
shashik493
fonte
6

Aqui, outra causa que encontrei: Ao usar o JQuery Mobile e o atributo de formulário data-ajax estiver definido como true, a matriz FILES ficará vazia. Portanto, defina data-ajax como false.

checkmate711
fonte
5

Verifique se o seu elemento de entrada possui um atributo 'name'. <input type="file" name="uploadedfile" />

Se isso estiver faltando, o $ _FILES estará vazio.

Adrian Parr
fonte
4

Eu estava lutando com o mesmo problema e testando tudo, não obtendo relatórios de erro e nada parecia estar errado. Eu tinha error_reporting (E_ALL) Mas, de repente, percebi que não havia verificado o log do apache e pronto! Houve um erro de sintaxe no script ...! (um "}" ausente)

Portanto, mesmo que isso seja algo evidente a ser verificado, pode ser esquecido ... No meu caso (linux), está em:

/var/log/apache2/error.log
Luis Rosety
fonte
3

Ninguém mencionou isso, mas isso me ajudou e não há muitos lugares na rede que o mencionem.

Verifique se o seu php.ini define a seguinte chave:

    upload_tmp_dir="/path/to/some/tmp/folder"

Você precisará verificar com seu host se eles querem que você use um caminho absoluto de arquivo do servidor. Você poderá ver outros exemplos de diretório no seu arquivo php.ini para determinar isso. Assim que eu defini, obtive valores no meu objeto _FILES.

Por fim, verifique se a pasta tmp e onde quer que você esteja movendo os arquivos têm as permissões corretas para que possam ser lidas e gravadas.

AaronP
fonte
2

Se você está tentando fazer upload de um conjunto de arquivos, então você pode precisar de aumentar max_file_uploadsem php.inique é pelo conjunto padrão de20

Nota : max_file_uploadsNÃO pode ser alterado fora do php.ini. Veja o PHP "Bug" # 50684

Tahir Yasin
fonte
2

Outro possível culpado é o redirecionamento do apache. No meu caso, eu tinha o httpd.conf do apache configurado para redirecionar determinadas páginas do nosso site para versões http e outras páginas para versões https da página, se elas ainda não estavam. A página na qual eu tinha um formulário com uma entrada de arquivo era uma das páginas configuradas para forçar o SSL, mas a página designada como a ação do formulário foi configurada para ser http. Portanto, a página enviava o upload para a versão ssl da página de ação, mas o apache o redirecionava para a versão http da página e os dados da postagem, incluindo o arquivo enviado, foram perdidos.

user2723315
fonte
2

Verifique seu php.ini em enable_post_data_reading = On , porque:

Desabilitar esta opção faz com que $ _POST e $ _FILES não sejam preenchidos . A única maneira de ler pós-dados será através do wrapper php: // input stream. (...)

Em http://php.net/manual/en/ini.core.php#ini.enable-post-data-reading

jmng
fonte
1

Se o seu script principal tiver http://Some_long_URL/index.phpcuidado, especifique o URL completo (com explícito index.phpe não apenas http://Some_long_URL) no actioncampo. Surpreendentemente, se não, o script certo é executado, mas com $ _FILES!

Gibbie
fonte
1

Encontrei o mesmo problema e descobri que o meu IDE fazia parte do problema. Eu estava iniciando o depurador diretamente do IDE (PHPStorm) em vez de apenas usar o navegador diretamente. O URL gerado pelo IDE era assim:

"...localhost:63342/CB_Upload/index.php?_ijt=j2hcbacqepj87bvg66ncuohvne"

e apenas usando:

"...localhost/CB_Upload/index.php"

funcionou muito bem. Minha configuração é PC / Windows 10 / WAMPSERVER 3.0.6 64bit

Marc M.
fonte
mesma coisa aqui, eu estava correndo em círculos por uma hora até agora! graças
EKanadily
1

Não confie no local da pasta temporária fornecido sys_get_temp_dirse você estiver em um ambiente de hospedagem compartilhada.

Aqui está mais uma coisa a verificar que ainda não foi mencionada ...

Eu assumi, naturalmente, que a pasta onde meu script PHP armazenava uploads temporários de arquivos era /tmp. Essa crença foi reforçada pelo fato de que echo sys_get_temp_dir() . PHP_EOL;retorna /tmp. Além disso, echo ini_get('upload_tmp_dir');não retorna nada.

Para verificar se o arquivo carregado aparece de fato brevemente na minha /tmppasta, adicionei uma sleep(30);declaração ao meu script (como sugerido aqui ) e naveguei para a minha /tmppasta no cPanel File Manager para localizar o arquivo. No entanto, não importa o quê, o arquivo enviado não foi encontrado em nenhum lugar.

Passei horas tentando determinar o motivo disso e implementei todas as sugestões oferecidas aqui.

Finalmente, depois de pesquisar os arquivos do meu site em busca da tmpdescoberta, descobri que meu site continha outras pastas nomeadas tmpem diretórios diferentes. Percebi que meu script PHP estava gravando os arquivos enviados para .cagefs/tmp. (A configuração "Mostrar arquivos ocultos" deve estar ativada no cPanel para exibir esta pasta.)

Então, por que a sys_get_temp_dirfunção retorna informações imprecisas?

Aqui está uma explicação da página do PHP.net para sys_get_temp_dir(ou seja, o comentário principal):

Se estiver executando em um sistema Linux em que systemd possui PrivateTmp = true (que é o padrão no CentOS 7 e talvez em outras distros mais recentes), essa função retornará "/ tmp", não o caminho verdadeiro, muito mais longo e dinâmico.

Esta postagem do SO também investiga o problema:

Grilos
fonte
0

Eu tenho o mesmo problema e nenhum dos temas foi meu erro. Verifique no seu arquivo .htaccess, se você tiver um, se "MultiViews" estiver ativado. Eu tive que desativá-los.

Murolack
fonte
0

Eu tive um problema semelhante e o problema estava no valor errado no htaccess, como shamittomar mencionou.

Mude php_value post_max_size 10MBparaphp_value post_max_size 10M

Johnny Vietnam
fonte
0

Eu estava vazio $_FILESporque depois que <form enctype="multipart/form-data" method="post">eu coloquei

</div>
<div style="clear:both"></div>

O código inicial era como

<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
<form enctype="multipart/form-data" method="post">
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>

Eu decidi modificar e

<div>
<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
<form enctype="multipart/form-data" method="post">
</div>
<div style="clear:both"></div>
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>
<div style="clear:both"></div>

Portanto, a conclusão é que depois <form enctype="multipart/form-data" method="post">deve ser <input name, type, ide não deve ser <div>ou algumas outras tags

Na minha situação, o código correto era

<div>
<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
</div>
<div style="clear:both"></div>
<form enctype="multipart/form-data" method="post">
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>
<div style="clear:both"></div>
Andris
fonte
0

Eu também tive problemas com $ _FILES vazios. A lista de verificação acima não menciona MultiViews em .htaccess, httpd.conf ou httpd-vhost.conf.

Se você tiver MultiViews definidos na diretiva de opções do seu diretório que contém o site, $ _FILES estará vazio, mesmo que o cabeçalho Content-Length esteja mostrando que o arquivo foi carregado.

gerteb
fonte
0

Se você estiver usando o JQuery Mobile

O uso de um formulário de várias partes com uma entrada de arquivo não é suportado pelo Ajax. Nesse caso, você deve decorar o formulário pai com data-ajax = "false" para garantir que o formulário seja enviado corretamente ao servidor.

<form action="upload.php" method="post" enctype="multipart/form-data"  data-ajax="false">
    Select image to upload:
    <input type="file" name="fileToUpload" id="fileToUpload">
    <input type="submit" value="Upload Image" name="submit">
</form>
Rajan
fonte
0

Desanexe o formulário da página que você está usando em uma página php simples que possua apenas o formulário e o código php, e teste-o assim.

Qualquer script de inicialização ou java pode limpar o _FILES []. Esse foi o meu caso

user2195463
fonte