Olá pessoal, como os posts sobre AJAX estão ficando bem populares no boteco resolvi fazer mais. Vocês devem lembrar do post que falei sobre AJAX com jQuery mas daquela forma não é possível enviar arquivos, pois para isso o navegador precisa ter suporte a e XMLHttpRequest Level 2 e se não tiver uma técnica bastante utilizada é com iframes(que possuem certas limitações), como isso é muito complicado é sempre melhor utilizar um plugin e o mais simples e eficiente que achei foi jQuery Form Plugin do malsup.

Primeiramente como sempre devemos inserir a biblioteca do jQuery e do plugin que iremos utilizar.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script> 
<script type="text/javascript" src="http://malsup.github.com/jquery.form.js"></script>

Depois iremos criar um formulário normal, só acrescentaremos a tag progress criada no HTML5, ela é bastante simples e possui basicamente dois atributos o max um valor inteiro que será o 100% da barra de progresso e o atributo value que será o valor atual do progresso.

<form action="post.php" method="post" id="form">
  
    <div id="file">
        <input type="file" name="file">
        <br ><br >
        <progress value="0" max="100"></progress><span id="porcentagem">0%</span>
 
    </div>
    <br />
 <input type="submit">
</form> 

E vamos onde a mágica realmente acontece:

$('#form').ajaxForm({
        uploadProgress: function(event, position, total, percentComplete) {
            $('progress').attr('value',percentComplete);
            $('#porcentagem').html(percentComplete+'%');
        },
        success: function(data) {
            $('progress').attr('value','100');
            $('#porcentagem').html('100%');
            $('pre').html(data);
        }   
         
});

Como vemos no trecho de código acima é selecionado o formulário que será enviado e chamamos o método ajaxForm adicionado pelo plugin jQuery Form Plugin passando dois parâmetros: uploadProgress e success que recebem referências de funções que serão chamadas no processo de requisição AJAX.

uploadProgress será chamada de tempos em tempo durante a requisição recebendo como parâmetro os valores de progresso da requisição.

Analisando um pouco melhor a função de uploadProgress na linha 3 selecionamos o elemento progress e configuramos seu atributo value com o valor da porcentagem já realizada da requisição o que irá fazer o indicador mudar sua visualização. Na linha 4 atualizamos o texto do indicador textual de porcentagem.

success será chamada somente se a requisição terminar sem erros. Ela recebe como parâmetro o texto do retorno da requisição que no nosso caso será feita ao script post.php, neste script trataremos o arquivo enviado através da variável $_FILES como usual e podemos salvar onde desejarmos.

Na linha 7 atualizamos para 100 o value do elemento progress pois é provável que a função uploadProgress tenha sido chamada pela ultima com uma porcentagem menor que 100%. Na linha 9 pegamos o retorno da requisição e colocamos dentro de um elemento pré-formatado pre, mas poderíamos dar qualquer outro tratamento para o retorno como por exemplo criar um elemento link para arquivo ou, se for uma imagem, criar uma miniatura da imagem enviada.

Você pode ver o exemplo do post

Uma aviso: os navegadores que não possuem suporte a “XMLHttpRequest Level 2” como o Opera11 e o IE8 por exemplo irão utilizar o iframes para realizar o upload, fazendo a opção uploadProgress não funcionar e por consequência a barra de progresso, embora o upload funcione. Recomendo testar se o navegar possui suporte a “XMLHttpRequest Level 2” se não tiver substituir a barra de progresso por um gif animado de carregando.

Recomendo ver a documentação do plugin jQuery Form Plugin que possui várias opções interessantes.