Created
August 30, 2013 21:52
-
-
Save fernando-basso/6394645 to your computer and use it in GitHub Desktop.
Multiple upload with javascript + Imagick
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class GalleryUp { | |
/** | |
* | |
* @var PDO Uma conexão estática com PDO (singleton). | |
*/ | |
private $db; | |
/** | |
* O diretório temporário para o upload e operações necessárias na imagem. | |
* | |
* @var String tmp_ups/ | |
*/ | |
private $dir; | |
/** | |
* | |
* @var String '/uploads/posts_images/' | |
*/ | |
private $final_dir = GALLERIES_DIR; | |
public function __construct(PDO $con) { | |
$this->db = $con; | |
$this->dir = ROOT . '/sysadm/gallery_up/tmp_ups'; | |
} | |
public function get_post_title( $post_id ) { | |
$sql = 'SELECT title FROM posts WHERE id = :post_id;'; | |
try { | |
$stmt = $this->db->prepare( $sql ); | |
$stmt->bindParam( ':post_id', $post_id, PDO::PARAM_INT ); | |
$stmt->execute(); | |
return ( $stmt->rowCount() > 0 ) ? $stmt->fetchColumn( 0 ) : FALSE; | |
} | |
catch ( PDOException $err ) { | |
die( 'Erro ao buscar título do conteúdo.' ); | |
} | |
} | |
public function save_images() { | |
$id = $_POST[ 'id' ]; | |
$tmpdir = "{$this->dir}/_{$id}"; | |
if ( isset( $_FILES ) ) { | |
// Tenta remover, se por algum motivo já existe. | |
self::remove_tmp_dir( $tmpdir ); | |
self::make_tmp_dir( $tmpdir ); | |
foreach( $_FILES AS $file ) { | |
// O nome do arquivo será o id_do_post-{01,02,03,etc}. OK por que nesse | |
// projeto cada conteúdo terá somente uma galeria. Se o conteúdo tivesse | |
// diversos albuns + galerias, teria que ser diferente. | |
$rand = $id . '-' . substr( rand(), 1, 5 ) . '-' . date('Ymdhis'); | |
$info = pathinfo( $file[ 'name' ] ); | |
$ext = $info[ 'extension' ]; | |
self::save_image( $file, $tmpdir, $rand, $ext ); | |
self::resize_image( $tmpdir, $rand, $ext ); | |
// A cada imagem redimensionada, devemos já salvar no destino, senão | |
// só temos o $rand final, o que faz com que a próxima imagem | |
// sempre sobrescreva a anterior. | |
if ( self::move_finished_files( $tmpdir, $this->final_dir, $rand ) ) { | |
// Estamo dentro do if por que não vamos salvar no banco uma | |
// imagem que não foi salva no HD. | |
self::save_on_database( $rand, $ext, $id ); | |
} | |
// Como estamos recebendo todos os arquivos de uma única vez, esse nome de | |
// arquivo com $num funciona. Se for um arquivo por requrest, num vai ser | |
// sempre zero e o nome do arquivo será sempre o mesmo, sobrescrevendo os | |
// arquivos já enviados. | |
} | |
} | |
// Vamos assumir que se chegou até aqui, é por que deu tudo certo. | |
return self::remove_tmp_dir( $tmpdir ); | |
} | |
private function save_image( $file, $dir, $rand, $ext ) { | |
if ( ! move_uploaded_file( $file[ 'tmp_name' ], "{$dir}/{$rand}.{$ext}" ) ) { | |
die( 'Erro ao salvar a imagem.' ); | |
} | |
} | |
private function resize_image( $dir, $rand, $ext ) { | |
$Img = new Imagick( "{$dir}/{$rand}.{$ext}" ); | |
$info = $Img->getImageGeometry(); | |
// Se tiver pelomenos 600px... | |
if ( $info[ 'width' ] > 600 ) { | |
$Img->scaleImage( 600, 0 ); | |
$Img->writeImage( "{$dir}/{$rand}-G.{$ext}" ); | |
$Img->scaleImage( 400, 0 ); | |
$Img->writeImage( "{$dir}/{$rand}-M.{$ext}" ); | |
} | |
else { | |
// Se não é nem 600 px, salva a grande e a média com o mesmo tamanho. | |
$Img->scaleImage( 400, 0 ); | |
$Img->writeImage( "{$dir}/{$rand}-G.{$ext}" ); | |
$Img->writeImage( "{$dir}/{$rand}-M.{$ext}" ); | |
} | |
// E a pequena (thumbnail) é sempre desse tamanho, no matter what! | |
$Img->scaleImage( 220, 180 ); | |
$Img->writeImage( "{$dir}/{$rand}-P.{$ext}" ); | |
$Img->scaleImage( 80, 60 ); | |
$Img->writeImage( "{$dir}/{$rand}-thumb.{$ext}" ); | |
$Img->destroy(); | |
self::remove_tmp_files( $dir, array( "{$rand}.{$ext}" ) ); | |
} | |
private function remove_tmp_files( $path, $files ) { | |
$flag = TRUE; | |
foreach( $files AS $f ): | |
if ( ! unlink( "{$path}/{$f}" ) ) | |
$flag = FALSE; | |
endforeach; | |
return $flag; | |
} | |
/** | |
* Cria o diretório temporário para o tratamento das imagens. | |
* | |
* @param String $path O caminho do diretório a ser criado. | |
*/ | |
private function make_tmp_dir( $path ) { | |
// Tem que ser 0777 senão não conseguimos visualizar a image, pois o novo | |
// dir fica com dono http e grupo http (ou www-data em debian servers ). | |
if ( ! mkdir( $path, 0777, TRUE ) ) | |
die( 'erro ao criar diretório temporário' ); | |
} | |
/** | |
* Remove um diretório. | |
* | |
* @param String $path O caminho do diretório a ser excluído. | |
* @return Boolean TRUE/FALSE | |
*/ | |
public function remove_tmp_dir( $path ) { | |
$flag = TRUE; | |
// Se o dir existe... | |
if ( file_exists( $path ) ) { | |
// Se há algo dentro dele (só um nível)... | |
if ( glob( "{$path}/*" ) ) { | |
foreach( glob( "{$path}/*" ) AS $f ) { | |
$flag = ( ! unlink( $f ) ) ? FALSE : TRUE; | |
} | |
} | |
// Se não, só remove o dir, pois estava vazio. | |
// Se deu erro no foreach, mas dá true aqui, a $flag será sobrescrita, | |
// o que não está correto. TODO. Concertar esse bug. | |
$flag = ( ! rmdir( $path ) ) ? FALSE : TRUE; | |
} | |
return $flag; | |
} | |
/** | |
* @param String $rand_name O nome randômico gerada para a imagem. | |
* @param Integer $id O id do registro a receber o nome da imagem. | |
* @return boolean TRUE on success, FALSE otherwise. | |
*/ | |
public function save_on_database( $rand, $ext, $post_id ) { | |
$sql = "INSERT INTO galleries ( post_id, rand_name, imgext ) | |
VALUES( :post_id, '{$rand}', '{$ext}' );"; | |
try { | |
$stmt = $this->db->prepare( $sql ); | |
$stmt->bindParam( ':post_id', $post_id, PDO::PARAM_INT ); | |
$res = $stmt->execute(); | |
} | |
catch( PDOException $err ) { | |
echo 'catch erro: ' . $err; | |
} | |
return $res; | |
} | |
public function get_images( $id ) { | |
$sql = 'SELECT post_id, rand_name, imgext FROM galleries WHERE post_id = :id;'; | |
try { | |
$stmt = $this->db->prepare( $sql ); | |
$stmt->bindParam( ':id', $id, PDO::PARAM_INT ); | |
$stmt->execute(); | |
return $stmt->rowCount() > 0 ? $stmt : FALSE; | |
} | |
catch( PDOExeption $err ) { | |
die( 'Erro ao buscar imagens da galleria: ' . $err ); | |
} | |
} | |
/** | |
* Move os arquivos redimensionados e recortados para o dir correto. | |
* | |
* Imagens de posts vão para um diretório, banners para outro. | |
* | |
* @param String $rand O nome randômico da imagem. | |
* @return boolean TRUE se moveu todos os arquivos, FALSE se pelo menos um falhou. | |
*/ | |
public function move_finished_files( $tmp_dir, $final_dir, $rand ) { | |
$flag = TRUE; | |
foreach ( glob( "{$tmp_dir}/{$rand}*" ) AS $filename ): | |
$name = pathinfo($filename)['basename']; | |
copy( $filename, "{$final_dir}/{$name}" ); | |
if ( ! unlink ( $filename ) ) { | |
$flag = FALSE; | |
} | |
endforeach; | |
return $flag; | |
} | |
/** | |
* Remove imagem do banco e do hd. | |
* | |
* Não precisa o caminho pois temos o $final_dir na classe. | |
*/ | |
public function remove_image( $rand ) { | |
if ( array_map( 'unlink', glob( "{$this->final_dir}/{$rand}*" ) ) ) { | |
$sql = 'DELETE FROM galleries WHERE rand_name = :rand;'; | |
try { | |
$stmt = $this->db->prepare( $sql ); | |
$stmt->bindParam( ':rand', $rand, PDO::PARAM_STR ); | |
if ( $stmt->execute() ) { | |
echo 1; // Mandar 1 em php é true em js. | |
} | |
} | |
catch( PDOExeption $err ) { | |
die( 'Erro ao remover a imagem da galeria: ' . $err ); | |
} | |
} | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment