Envio de multipart/formdata com jQuery.ajax
I'tenho um problema ao enviar um arquivo para um script PHP do lado do servidor usando jQuery's ajax-function.
It's possible to get the File-List with $('#fileinput').attr('files')
but how is it possible to send this Data to the server? O array resultante ($_POST
) no php-script do lado do servidor é 0 (NULL
) quando se utiliza a entrada de arquivo.
Eu sei que é possível (embora eu não'não encontrei nenhuma solução jQuery até agora, apenas código Prototye (http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html)).
Isso parece ser relativamente novo, então não mencione que o upload de arquivos seria impossível via XHR/Ajax, porque ele's definitivamente funciona.
Eu preciso da funcionalidade no Safari 5, FF e Chrome seria bom, mas não é essencial.
O meu código por agora é:
$.ajax({
url: 'php/upload.php',
data: $('#file').attr('files'),
cache: false,
contentType: 'multipart/form-data',
processData: false,
type: 'POST',
success: function(data){
alert(data);
}
});
Começando pelo Safari 5/Firefox 4, é mais fácil utilizar a classe
FormData
:Então agora você tem um objeto
FormData
, pronto para ser enviado junto com o XMLHttpRequest.É imperativo que você defina a opção
contentType' para
false', forçando jQuery a não adicionar um cabeçalhoContent-Type' para você, caso contrário, a string de limite estará faltando. Além disso, você deve deixar o flag
processDatadefinido como falso, caso contrário, jQuery irá tentar converter seu
FormData` em uma string, o que falhará.Agora você pode recuperar o arquivo em PHP usando:
(Há apenas um arquivo,
file-0
, a menos que você tenha especificado o atributomúltiplo
na entrada do seu arquivo, neste caso, os números serão incrementados com cada arquivo).**Usando a emulação FormData para navegadores mais antigos***
**Criar dados do formulário a partir de um formulário existente***
Em vez de iterar manualmente os arquivos, o objeto FormData também pode ser criado com o conteúdo de um objeto form existente:
**Utilize um array nativo de PHP ao invés de um contador***
Basta dar o mesmo nome aos elementos do seu ficheiro e terminar o nome entre parênteses:
$_FILES['file']
será então um array contendo os campos de carregamento de arquivos para cada arquivo carregado. Eu realmente recomendo isso sobre minha solução inicial, pois é mais simples iterar sobre.Só queria acrescentar um pouco a resposta do Raphael'a grande resposta. Aqui's como obter o PHP para produzir os mesmos
$_FILES
, independentemente de você usar JavaScript para enviar.Formulário HTML:
O PHP produz este
$_FILES
, quando submetido sem JavaScript:Se você fizer aprimoramento progressivo, usando o Raphael's JS para submeter os arquivos...
... isto é o que o array PHP's
$_FILES
parece, depois de utilizar aquele JavaScript para enviar:Isso'é um bom array, e na verdade no que algumas pessoas transformam
$_FILES
, mas eu acho isso'é útil para trabalhar com o mesmo$_FILES
, independentemente se o JavaScript foi utilizado para enviar. Então, aqui estão algumas pequenas mudanças no JS:(14 de Abril 2017 editar: removi o elemento form do construtor do FormData() -- que corrigiu este código no Safari).
Esse código faz duas coisas.
form
tenha a classe putImages, tudo o resto é tratado automaticamente. Ou seja, oinput
não precisa ter nenhum nome especial.Com estas alterações, submeter com JavaScript agora produz precisamente a mesma matriz
$_FILES
que submeter com HTML simples.Acabei de construir esta função com base em algumas informações que li.
Utilize-o como se utilizasse
.serialize()
, em vez disso basta colocar.serializefiles();
.Trabalhar aqui nos meus testes.