Há algum tempo estive pesquisando sobre como fazer um upload em php e mostrar uma barra de progresso. Depois de muito pesquisar encontrei em algumas buscas que falando para usar uma das extenções APC ou uploadprogress, mas não obtive muito sucesso nos diversos exemplos que se encontram na internet, tavez pelo fato de eu estar usando como servidor o Internet Information Services (IIS 7). Então eu encontrei um plugin e nesse artigo vou mostrar como usar uma de suas funcionalidades para fazer uma barra de progresso personalizada em php. Nesse artigo vou usar o IIS 7, PHP 5.3.6, o SWFUpload (http://swfupload.org/) e o jQuery User Interface ( http://jqueryui.com/).

Primeiramente vamos fazer o download do plugin de upload em http://code.google.com/p/swfupload/downloads/list

Vou usar nesse exemplo a versão SWFUpload v2.2.0.1 Samples.

Descompactei os arquivos detro de uma pasta no meu servidor local chamada “swfupload”

Tela de exemplos do SWFUpload no servidor local

Figura 1. Tela de exemplos do SWFUpload no servidor local

Em seguida fazer o download do jQuery UI. Nesse exemplo só irei usar o widget Progressbar do jQuery disponível para download nesse link http://jqueryui.com/download(Caso você queira fazer o download de todo o jQuery UI lembre-se de alterar as chamadas subsequentes que serão feitos nesse exemplo, para os seus arquivos) Descompactei os arquivos dentro de uma pasta no meu servidor local chamada de “jqueryui”

Tela de boas vindas do jQuery UI no servidor local

Figura 2. Tela de boas vindas do jQuery UI no servidor local

Nesse exemplo para fazer a barra de progresso personalizada usarei o Speed Plugin Demo do SWFUpload

Tela do plugin SWFUpload.Speed

Figura 3. Tela do plugin SWFUpload.Speed

Conforme podemos ver na imagem o SWFUpload oferece várias funcionalidades como a velocidade atual, porcentagem de upload, tamanho do arquivo, etc.

Vamos abrir o código fonte do arquivo http://localhost/swfupload/demos/speeddemo/index.php e explicar melhor outras funcionalidades.

Vou destacar as linhas 29 a 77 desse arquivo.

Listagem 1. Trecho da página index.php com o script de configuração do SWFUpload.Speed


<script type="text/javascript">
	var swfu;

	window.onload = function() {
		var settings = {
			flash_url : "../swfupload/swfupload.swf",
			upload_url: "upload.php",
			file_size_limit : "100 MB",
			file_types : "*.*",
			file_types_description : "All Files",
			file_upload_limit : 100,
			file_queue_limit : 0,

			debug: false,

			// Button settings
			button_image_url: "images/XPButtonUploadText_61x22.png",
			button_width: "61",
			button_height: "22",
			button_placeholder_id: "spanButtonPlaceHolder",
			
			moving_average_history_size: 40,
			
			// The event handler functions are defined in handlers.js
			file_queued_handler : fileQueued,
			file_dialog_complete_handler: fileDialogComplete,
			upload_start_handler : uploadStart,
			upload_progress_handler : uploadProgress,
			upload_success_handler : uploadSuccess,
			upload_complete_handler : uploadComplete,
			
		custom_settings : {
			tdFilesQueued : document.getElementById("tdFilesQueued"),
			tdFilesUploaded : document.getElementById("tdFilesUploaded"),
			tdErrors : document.getElementById("tdErrors"),
			tdCurrentSpeed : document.getElementById("tdCurrentSpeed"),
			tdAverageSpeed : document.getElementById("tdAverageSpeed"),
			tdMovingAverageSpeed : document.getElementById("tdMovingAverageSpeed"),
			tdTimeRemaining : document.getElementById("tdTimeRemaining"),
			tdTimeElapsed : document.getElementById("tdTimeElapsed"),
			tdPercentUploaded : document.getElementById("tdPercentUploaded"),
			tdSizeUploaded : document.getElementById("tdSizeUploaded"),
			tdProgressEventCount : document.getElementById("tdProgressEventCount")
			}
		};

		swfu = new SWFUpload(settings);
	 };
</script>

nessas linhas você irá encontrar parâmetros de configuração muito importantes como:

upload_url (linha 35)-> esse é o arquivo que será executado logo após o termino do upload, para podermos mover o upload feito para uma pasta de nossa escolha

file_size_limit (linha 36) -> usado para configurar o tamanho máximo permitido para o upload

file_types (linha 37) -> usado para configurar quais arquivos serão aceitos

Nesse arquivo index.php vou adicionar o código no head

Listagem 2. Trecho da página index.php com o script que instancia a nossa barra de progresso em 0%


<link rel="stylesheet" 
      href="http://localhost/jqueryui/css/ui-lightness/jquery-ui-1.8.18.custom.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
</script>
<script src="http://localhost/jqueryui/js/jquery-ui-1.8.18.custom.min.js"></script>
<script src="http://localhost/jqueryui/ui/jquery.ui.widget.js"></script>
<script src="http://localhost/jqueryui/ui/jquery.ui.progressbar.js"></script>
<script>
$(function() {
	$("#progressbar").progressbar({value: 0}); //Instancia o progressbar
});
</script>

e vamos adicionar o código no body da página

Listagem 3. Trecho da página index.php com o HTML onde será mostrada a nossa barra de progresso


<div id="progressbar"></div>

obs.: para mais informações sobre como usar o Progressbar do jQuery visite a página http://jqueryui.com/demos/progressbar/

No index.php, citado anteriormente existe uma referência para um arquivo chamado “handlers.js” que é o responsável por atualizar as informações em tempo real no navegador.

Estamos procurando mais espeficamente a função “updateDisplay”, nessa função o SWFUpload retorna a porcentagem do upload que é o que usaremos para atualizar nossa barra de progresso.

Veja no código a seguir que eu adicionei na última linha dessa função uma instancia para o widget do jQuery usando o método “file.percentUploaded” que retorna um número de 0 a 100.

Listagem 4. Trecho do código handlers.js com o script de atualização dos dados de upload em tempo real do SWFUpload


function updateDisplay(file) {
	this.customSettings.tdCurrentSpeed.innerHTML = 
         SWFUpload.speed.formatBPS(file.currentSpeed);
	this.customSettings.tdAverageSpeed.innerHTML = 
         SWFUpload.speed.formatBPS(file.averageSpeed);
	this.customSettings.tdMovingAverageSpeed.innerHTML = 
         SWFUpload.speed.formatBPS(file.movingAverageSpeed);
	this.customSettings.tdTimeRemaining.innerHTML = 
         SWFUpload.speed.formatTime(file.timeRemaining);
	this.customSettings.tdTimeElapsed.innerHTML = 
         SWFUpload.speed.formatTime(file.timeElapsed);
	this.customSettings.tdPercentUploaded.innerHTML = 
        SWFUpload.speed.formatPercent(file.percentUploaded); 
       //file.percentUploaded é o que precisamos para atualizar a barra de progresso
	this.customSettings.tdSizeUploaded.innerHTML = 
         SWFUpload.speed.formatBytes(file.sizeUploaded);
	this.customSettings.tdProgressEventCount.innerHTML = 
         this.customSettings.progressCount;
	
	$("#progressbar").progressbar({value: file.percentUploaded}); 
        //aqui que acontece a "mágica" da barra de progresso
}

Com isso a nossa barra de progresso já está funcionando mas ainda falta mover o arquivo para uma pasta acessível em nosso servidor. Então vamos criar uma pasta chamada “files” dentro do diretório do SWFUpload que será o respositório dos arquivos.


Figura 4. Diretório onde os arquivos serão salvos

E por fim vamos abrir o arquivo upload.php (http://localhost/swfupload/demos/speeddemo/upload.php) que foi configurado para ser executado após o término do upload no parâmetro “upload_url” da nossa página index.php.

Vamos usar a função do php “move_uploaded_file” para mover o arquivo que fizemos o upload para a nossa pasta “files” dentro do nosso servidor. Confira o código a seguir de como ficará o nosso arquivo upload.php

Obs.: Para mais informações sobre a função “move_uploaded_file” acesse http://php.net/manual/pt_BR/function.move-uploaded-file.php

Listagem 5. Código upload.php que moverá o nosso arquivo para a pasta “files”


<?php
/*Work-around for setting up a session 
because Flash Player doesn't send the cookies*/
	if (isset($_POST["PHPSESSID"])) {
		session_id($_POST["PHPSESSID"]);
	}
	session_start();

	// The Demos don't save files
	
	
	if (!isset($_FILES["Filedata"]) 
        ||
        !is_uploaded_file($_FILES["Filedata"]["tmp_name"])
        || $_FILES["Filedata"]["error"] != 0) {
		echo "There was a problem with the upload";
	}
	
	move_uploaded_file($_FILES["Filedata"]["tmp_name"],
        "files/".$_FILES["Filedata"]["name"]);
/*Aqui é onde movemos o nosso upload para a pasta files
 acessível pelo servidor */
	
	exit(0);
?>

Depois de todas essas alterações vamos testar para ver como ficou.

Veja abaixo a nossa barra de progresso de upload.


Figura 5. Barra de progresso do upload em ação

E depois confira o arquivo dentro da pasta “files” no servidor web


Figura 6. Pasta “files” com o nosso arquivo já upado

Fico por aqui e até o próximo artigo.