Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Thiago Retondar

Classe Upload

Recommended Posts

Faala, galera!

 

Comecei a estudar PHP faz pouco tempo e para começar a brincar, resolvi criar um classe para Upload de arquivos.

 

:seta: funciona com upload simples e múltiplo;

:seta: tem a opção de setar o tamanho máximo do arquivo, que por padrão é 2Mb

:seta: método para setar o diretório

:seta: método para setar quais tipos de arquivos são válidos (padrão é *)

:seta: método send() para fazer o upload

 

Gostaria de receber opiniões/dicas para eu aprender melhor sobre orientação a objeto, design pattern, etc.

 

Tentei documentar da forma mais esclarecedora (acabei treinando meu inglês enferrujado assobiando.gif), mas não sei se está "correto"

 

Upload.class.php

 

 

<?php

/**
* @author Thiago Retondar
* @version 1.2
* @since 2011-07-17
* @license http://opensource.org/licenses/gpl-3.0.html
*/

class Upload {
/**
 * @var array
 */
private $files;

/**
 * @var integer
 */
private $amount;

/**
 * @var boolean
 */
private $multiple = false;

/**
 * @var string
 */
private $directory;

/**
 * @var mixed
 */
private $maxsize = 2;

/**
 * @var string
 */
private $filetypes = "*"; 

/**
 * @var array
 */
private $errors = array();

/**
 * @var boolean
 */
private $showError = true;

/**
 * Will receive the superglobal $_FILES[]
 * @param array $files
 * @param boolean $show_error Specifies whether the error appears or not
 */
public function __construct(array $files, $show_error = true) {
	$this->files = $files;

	if(is_array($files['name'])) {
		$this->amount 	= count($files['name']);
		$this->multiple = true;
	}

	if(isset($show_error) && is_bool($show_error))
		$this->showError = $show_error;

	return $this;
}

/**
 * Will set the directory to upload the files
 * @param string $dir
 */
public function setDir($dir) {
	if(is_string($dir) && trim($dir) != "")
		$this->directory = $dir;

	return $this;
}

/**
 * Will set the maximum size of the files
 * @param number $mbytes
 */
public function maxSize($mbytes) {
	if(is_numeric($mbytes))
		$this->maxsize = $mbytes;

	return $this;
}

/**
 * @var number
 */
private function mbyteToByte($megabyte) {
	if(is_numeric($megabyte))
		return $megabyte * 1048576; // 1 megabyte equals 1.048.576 bytes
}

/**
 * Will set the MIME types (file extension). By default is a
 * string ("*") to accept all the file extensions *BUT* is
 * recommended
 * to explicit the file types
 * @param array $filetypes
 */
public function fileTypes(array $filetypes) {
	$this->filetypes = $filetypes;
	return $this;
}

/**
 * Use this method to upload the files put on files() method;
 */
public function send() {
	if($this->directory === null || !is_writable($this->directory)){ // Verifies if the directory was setted and if has writable permission
		trigger_error('O diretório para uploads dos arquivos não foi definido ou não tem permissão de escrita!');
		exit;
	} elseif(is_dir($this->directory)) { // Verifies if the directory exists
		$name 	= $this->files['name'];
		$tmp_name = $this->files['tmp_name'];
		$size 	= $this->files['size'];
		$type 	= $this->files['type'];

		if($this->multiple) // Multiple upload
			for($f = 0; $f < $this->amount; $f++) {
				if($this->verifyFile($name[$f], $size[$f], $type[$f]) !== false)
					$this->uploadFile($tmp_name[$f], $name[$f]);
			}
		else // Single upload
			if($this->verifyFile($name, $size, $type) !== false)
				$this->uploadFile($tmp_name, $name);

		$this->showErrors($this->errors);
	} else { // If the directory doesn't exist
		trigger_error('Defina um diretório válido!');
		exit;		
	}
}

/**
 * Verifies if the file that will be sent is correct
 * @param string $file The file name
 * @param string $size The file size
 * @param string $type The file type
 */
private function verifyFile($file, $size, $type){
	if(!empty($file)) {
		if($size >= $this->mbyteToByte($this->maxsize)) {
			array_push($this->errors, 'O <strong>'. $file .'</strong> excedeu o tamanho máximo de <strong>'. $this->maxsize .'</strong>');
			return false;
		} elseif(is_array($this->filetypes) && !in_array($type, $this->filetypes)) {
			array_push($this->errors, 'O <strong>'. $file .'</strong> não é um tipo de arquivo permitido!');
			return false;
		}
	}
}

/**
 * Verifies if is uploaded file by the form and if can move the file 
 * to the directory specified
 * @param string $tmp_name The temporary name of the uploaded file
 * @param string $name the real name of the uploaded file 
 */
private function uploadFile($tmp_name, $name){
	if(is_uploaded_file($tmp_name) && !move_uploaded_file($tmp_name, $this->directory . $name)) {
		array_push($this->errors, 'Não foi possível enviar o arquivo <strong>'. $name .'</strong>. Verifique o arquivo e tente novamente.');
		return false;
	} else {
		return true;
	}
}

/**
 * Show errors (or not, if the attribute $showErrors is false) if there's
 * @param array $errors All the errors (in an array)
 */
private function showErrors(Array $errors) {
	if($this->showError && count($errors) > 0)
		foreach($errors as $error)
			echo "<p>". $error ."</p>";
}
}

?>

 

Exemplos para uso:

 

Upload Simples

<form action="" method="post" enctype="multipart/form-data">
<label>
	<input type="file" name="image" />
</label>
<button type="submit" name="up_imgs">Enviar imagens</button>
</form>

<?php
   if(isset($_POST['up_imgs'])){
       require_once('../Class/Upload.class.php');
       // se não quiser que apareça os erros do processo de upload, instancie com o segundo parâmetro sendo "false"
           // $up = new Upload($_FILES['image'], false);
      		$up = new Upload($_FILES['image']);
      		$up->maxSize(0.3) // Declare sempre em megabytes, logo, se você quiser 200Kb, basta declarar 0.2
              	->setDir('/var/www/Upload/Images_Uploaded/') // o diretório deve terminar com uma barra "/"
              	->fileTypes(array('image/jpeg', 'image/png', 'image/gif')) // os tipos de arquivo devem estar em um array. Por padrão, todos são aceitos.
              	->send(); // para finalizar, chame o método send() para fazer o Upload.
   }?>

 

 

Upload múltiplo

<form action="" method="post" enctype="multipart/form-data">
<button type="button" name="add_field">Adicionar campo</button>
<label>
	<input type="file" name="image[]" />
</label>
<label>
	<input type="file" name="image[]" />
</label>
<button type="submit" name="up_imgs">Enviar imagens</button>
</form>

<?php
   if(isset($_POST['up_imgs'])){
       require_once('../Class/Upload.class.php');
       // se não quiser que apareça os erros do processo de upload, instancie com o segundo parâmetro sendo "false"
           // $up = new Upload($_FILES['image'], false);
      		$up = new Upload($_FILES['image'], false);
      		$up->setDir('/var/www/Upload/Images_Uploaded/') // o diretório deve terminar com uma barra "/"
              	->fileTypes(array('image/jpeg', 'image/png', 'image/gif')) // os tipos de arquivo devem estar em um array. Por padrão, todos são aceitos.
              	->send(); // para finalizar, chame o método send() para fazer o Upload.
       // Veja que o método maxSize() não foi chamado, por tanto, vai ficar com o valor padrão, que é 2MB
   }?>

Bem é isso... Como já disse, essa é minha primeira classe (me senti professor agora HUAHUAHUAH rolleyes.gif), então se alguém quiser opinar, elogiar, dar alguma dica, etc, por favor, eu agradeço.

 

:thumbsup:

Compartilhar este post


Link para o post
Compartilhar em outros sites

A única sugestão relevante que eu tenho é trocar:

trigger_error('O diretório para uploads dos arquivos não foi definido ou não tem permissão de escrita!');

Por:

throw new Exception('O diretório para uploads dos arquivos não foi definido ou não tem permissão de escrita!');

 

Para permitir um tratamento mais apurado pelo caller, invés de somente jogar um erro...

 

De resto, acredito que esteja bom, usando Fluent Interface, recurso bacana... Muito nego mais experiente por aí quando vai fazer esse tipo de coisa faz lambança...

 

Parabéns aew Thiago :joia:

 

Nesse caso não cabe nenhum design pattern, pois muitas vezes (a maioria dos que eu conheço, pelo menos) se referem a conjuntos de classes/objetos e suas relações e não a um só...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vlw, Rick! =)

 

Dei uma pesquisa sobre o básico disso, acho que sempre fugi desse assunto... ahuahauha :assobiando:

 

Havia colocado um bloco try envolvendo todos os ifs/else no método send() mas achei porco e resolvi criar uma função (private) para fazer a validação do diretório:

 

/**
* Verifies if the directory exists and if it it
* ready to receive the file
* @return boolean
*/
private function verifyDir() {
if($this->directory === null      ||  // Was it set?
   !is_writable($this->directory) ||  // Does it have permission?
   !is_dir($this->directory))         // Is it a directory?
{ 
	throw new Exception('O diretório para uploads dos arquivos não foi definido corretamente ou não tem permissão de escrita!');
	return false;
	exit;
} else {
	return true;
}
}

 

Ficando assim:

 

Upload.class.php

 

<?php

/**
* @author Thiago Retondar
* @version 1.3
* @since 2011-07-17
* @license http://opensource.org/licenses/gpl-3.0.html
*/

class Upload {
/**
 * @var array
 */
private $files;

/**
 * @var integer
 */
private $amount;

/**
 * @var boolean
 */
private $multiple = false;

/**
 * @var string
 */
private $directory;

/**
 * @var mixed
 */
private $maxsize = 2;

/**
 * @var string
 */
private $filetypes = "*"; 

/**
 * @var array
 */
private $errors = array();

/**
 * @var boolean
 */
private $showError = true;

/**
 * Will receive the superglobal $_FILES[]
 * @param array $files
 * @param boolean $show_error Specifies whether the error appears or not
 */
public function __construct(array $files, $show_error = true) {
	$this->files = $files;

	if(is_array($files['name'])) {
		$this->amount 	= count($files['name']);
		$this->multiple = true;
	}

	if(isset($show_error) && is_bool($show_error))
		$this->showError = $show_error;

	return $this;
}

/**
 * Will set the directory to upload the files that by
 * default all types are accepted, *BUT* is recommended
 * to explicit the file types
 * @param string $dir
 */
public function setDir($dir) {
	if(is_string($dir) && trim($dir) != "")
		$this->directory = $dir;

	return $this;
}

/**
 * Will set the maximum size of the files
 * @param number $mbytes
 */
public function maxSize($mbytes) {
	if(is_numeric($mbytes))
		$this->maxsize = $mbytes;

	return $this;
}

/**
 * @var number
 */
private function mbyteToByte($megabyte) {
	if(is_numeric($megabyte))
		return $megabyte * 1048576; // 1 megabyte equals 1.048.576 bytes
}

/**
 * Will set the MIME types (file extension). By default is a
 * string ("*") to accept all the file extensions *BUT* is
 * recommended
 * to explicit the file types
 * @param array $filetypes
 */
public function fileTypes(array $filetypes) {
	$this->filetypes = $filetypes;
	return $this;
}

/**
 * Use this method to upload the files put on files() method;
 */
public function send() {
	try {
		if($this->verifyDir()) {
			$name     = $this->files['name'];
			$tmp_name = $this->files['tmp_name'];
			$size     = $this->files['size'];
			$type     = $this->files['type'];

			if($this->multiple) // Multiple upload
				for($f = 0; $f < $this->amount; $f++) {
					if($this->verifyFile($name[$f], $size[$f], $type[$f]) !== false)
						$this->uploadFile($tmp_name[$f], $name[$f]);
				}
			else // Single upload
				if($this->verifyFile($name, $size, $type) !== false)
					$this->uploadFile($tmp_name, $name);

			$this->showErrors($this->errors);
		}
	} catch(Exception $e) {
		echo $e->getMessage();
	}
}

/**
 * Verifies if the directory exists and if it it
 * ready to receive the file
 * @return boolean
 */
private function verifyDir() {
	if($this->directory === null      ||  // Was it set?
	   !is_writable($this->directory) ||  // Does it have permission?
	   !is_dir($this->directory))         // Is it a directory?
	{ 
		throw new Exception('O diretório para uploads dos arquivos não foi definido corretamente ou não tem permissão de escrita!');
		return false;
		exit;
	} else {
		return true;
	}
}

/**
 * Verifies if the file that will be sent is correct
 * @param string $file The file name
 * @param string $size The file size
 * @param string $type The file type
 * @return boolean
 */
private function verifyFile($file, $size, $type){
	if(!empty($file)) {
		if($size >= $this->mbyteToByte($this->maxsize)) {
			array_push($this->errors, 'O <strong>'. $file .'</strong> excedeu o tamanho máximo de <strong>'. $this->maxsize .'</strong>');
			return false;
		} elseif(is_array($this->filetypes) && !in_array($type, $this->filetypes)) {
			array_push($this->errors, 'O <strong>'. $file .'</strong> não é um tipo de arquivo permitido!');
			return false;
		}
	}
}

/**
 * Verifies if is uploaded file by the form and if can move the file 
 * to the directory specified
 * @param string $tmp_name The temporary name of the uploaded file
 * @param string $name the real name of the uploaded file
 * @return boolean
 */
private function uploadFile($tmp_name, $name){
	if(is_uploaded_file($tmp_name) && !move_uploaded_file($tmp_name, $this->directory . $name)) {
		array_push($this->errors, 'Não foi possível enviar o arquivo <strong>'. $name .'</strong>. Verifique o arquivo e tente novamente.');
		return false;
	} else {
		return true;
	}
}

/**
 * Show errors (or not, if the attribute $showErrors is false) if there's
 * @param array $errors All the errors (in an array)
 * @return string HTML to show the errors inside the tags <p>
 */
private function showErrors(Array $errors) {
	if($this->showError && count($errors) > 0)
		foreach($errors as $error)
			echo "<p>". $error ."</p>";
}
}

?>

Seria isso o que você sugeriu fazer? Ou tem alguma outra melhor forma?Vlw :thumbsup:

 

EDIT: Estou tendo problemas com BBCode... Só aqui?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Adicionei o método Upload::getFileName() com base nesse tópico :seta: http://forum.imasters.com.br/topic/439224-ajuda-upload/

 

 

 

<?php

/**
* @author Thiago Retondar
* @version 1.4
* @since 2011-07-17
* @license http://opensource.org/licenses/gpl-3.0.html
*/

class Upload {
/**
 * @var array
 */
private $files;

/**
 * @var integer
 */
private $amount;

/**
 * @var boolean
 */
private $multiple = false;

/**
 * @var string
 */
private $directory;

/**
 * @var mixed
 */
private $maxsize = 2;

/**
 * @var string
 */
private $filetypes = "*"; 

/**
 * @var array
 */
private $errors = array();

/**
 * @var boolean
 */
private $showError = true;

/**
 * Will receive the superglobal $_FILES[]
 * @param array $files
 * @param boolean $show_error Specifies whether the error appears or not
 */
public function __construct(array $files, $show_error = true) {
	$this->files = $files;

	if(is_array($files['name'])) {
		$this->amount 	= count($files['name']);
		$this->multiple = true;
	}

	if(isset($show_error) && is_bool($show_error))
		$this->showError = $show_error;

	return $this;
}

/**
 * Will set the directory to upload the files that by
 * default all types are accepted, *BUT* is recommended
 * to explicit the file types
 * @param string $dir
 */
public function setDir($dir) {
	if(is_string($dir) && trim($dir) != "")
		$this->directory = $dir;

	return $this;
}

/**
 * Will set the maximum size of the files
 * @param number $mbytes
 */
public function maxSize($mbytes) {
	if(is_numeric($mbytes))
		$this->maxsize = $mbytes;

	return $this;
}

/**
 * @var number
 */
private function mbyteToByte($megabyte) {
	if(is_numeric($megabyte))
		return $megabyte * 1048576; // 1 megabyte equals 1.048.576 bytes
}

/**
 * Will set the MIME types (file extension). By default is a
 * string ("*") to accept all the file extensions *BUT* is
 * recommended
 * to explicit the file types
 * @param array $filetypes
 */
public function fileTypes(array $filetypes) {
	$this->filetypes = $filetypes;
	return $this;
}

/**
 * Gives you the file names
 * @return array OR string
 */
public function getFileName(){
	return $this->files['name'];
}

/**
 * Use this method to upload the files put on files() method;
 */
public function send() {
	try {
		if($this->verifyDir()) {
			$name     = $this->files['name'];
			$tmp_name = $this->files['tmp_name'];
			$size     = $this->files['size'];
			$type     = $this->files['type'];

			if($this->multiple) // Multiple upload
				for($f = 0; $f < $this->amount; $f++) {
					if($this->verifyFile($name[$f], $size[$f], $type[$f]) !== false)
						$this->uploadFile($tmp_name[$f], $name[$f]);
				}
			else // Single upload
				if($this->verifyFile($name, $size, $type) !== false)
					$this->uploadFile($tmp_name, $name);

			$this->showErrors($this->errors);
		}
	} catch(Exception $e) {
		echo $e->getMessage();
	}
}

/**
 * Verifies if the directory exists and if it is
 * ready to receive the file
 * @return boolean
 */
private function verifyDir() {
	if($this->directory === null      ||  // Was it set?
	   !is_writable($this->directory) ||  // Does it have permission?
	   !is_dir($this->directory))         // Is it a directory?
	{ 
		throw new Exception('O diretório para uploads dos arquivos não foi definido corretamente ou não tem permissão de escrita!');
		return false;
		exit;
	} else {
		return true;
	}
}

/**
 * Verifies if the file that will be sent is correct
 * @param string $file The file name
 * @param string $size The file size
 * @param string $type The file type
 * @return boolean
 */
private function verifyFile($file, $size, $type){
	if(!empty($file)) {
		if($size >= $this->mbyteToByte($this->maxsize)) {
			array_push($this->errors, 'O <strong>'. $file .'</strong> excedeu o tamanho máximo de <strong>'. $this->maxsize .'</strong>');
			return false;
		} elseif(is_array($this->filetypes) && !in_array($type, $this->filetypes)) {
			array_push($this->errors, 'O <strong>'. $file .'</strong> não é um tipo de arquivo permitido!');
			return false;
		}
	}
}

/**
 * Verifies if is uploaded file by the form and if can move the file 
 * to the directory specified
 * @param string $tmp_name The temporary name of the uploaded file
 * @param string $name the real name of the uploaded file
 * @return boolean
 */
private function uploadFile($tmp_name, $name){
	if(is_uploaded_file($tmp_name) && !move_uploaded_file($tmp_name, $this->directory . $name)) {
		array_push($this->errors, 'Não foi possível enviar o arquivo <strong>'. $name .'</strong>. Verifique o arquivo e tente novamente.');
		return false;
	} else {
		return true;
	}
}

/**
 * Show errors (or not, if the attribute $showErrors is false) if there's
 * @param array $errors All the errors (in an array)
 * @return string HTML to show the errors inside the tags <p>
 */
private function showErrors(Array $errors) {
	if($this->showError && count($errors) > 0)
		foreach($errors as $error)
			echo "<p>". $error ."</p>";
}
}

?>

 

 

 

:thumbsup:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá, Thiago, Algumas coisinhas desnecessárias que eu notei no seu código, por exemplo:

throw new Exception('O diretório para uploads dos arquivos não foi definido corretamente ou não tem permissão de escrita!');
return false;
exit;

Quando você dispara exception, ou faz um return, qualquer bloco de código depois do return ou da exception, não será executado..

Resumindo, seu return, exit não vai ter o efeito esperado.

 

;)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vlw, Andrey! :joia:

 

Ficou assim:

/**
* Verifies if the directory exists and if it is
* ready to receive the file
* @return boolean
*/
private function verifyDir() {
if($this->directory === null      ||  // Was it set?
   !is_writable($this->directory) ||  // Does it have permission?
   !is_dir($this->directory))         // Is it a directory?
{ 
	throw new Exception('O diretório para uploads dos arquivos não foi definido corretamente ou não tem permissão de escrita!');
} else {
	return true;
}
}

:thumbsup:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu ainda chego a este nível de OO!

=)

 

Parabéns, show de bola!

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.