Dividir Arquivos em várias partes – Dissecando PHP
Imagine a seguinte situação, você está baixando um arquivo da internet muito grande, ficou horas esperando o download terminar e quando está quase no final, de repente acontece um imprevisto e você precisa recomeçar do zero. Chato, não? Claro que existem programas que gerenciam downloads e permitem você parar downloads e começar mais tarde do ponto onde parou, mas também é verdade que muitos usuários não usam esses gerenciadores. Nesses casos uma solução interessante é dividir o download em várias partes e permitir que o usuário baixe cada parte separadamente e depois junte elas e tenha seu arquivo restaurado.
Além disso, dividir arquivos em várias partes pode ser útil para outros fins, como por exemplo para fazer upload de arquivos muito grandes em servidores que limitam o tamanho máximo de cada arquivo, então resolvi criar uma classe em PHP para dividir arquivos remotamente, veja o código, continuo depois.
class PWS_file_splitter{
protected $file_name;
protected $target_folder;
protected $piece_size;
const BUFFER = 1024;
public function PWS_file_splitter($file_name, $target="downloads",$piece_size=10){
$this->file_name = $file_name;
$this->target_folder = $target;
$this->piece_size = $piece_size;
$this->split_now();
}
public function split_now(){
$piece = 1048576 * $this->piece_size;
$current = 0;
$splitnum = 1;
if(!file_exists($this->target_folder)) {
if(!mkdir($this->target_folder)) {
die("Ocorreu um erro ao criar o caminho de destino");
}
}
if(!$handle = fopen($this->file_name, "rb")) {
die("Erro ao abrir o arquivo $this->file_name para leitura!");
}
$base_filename = basename($this->file_name);
$piece_name = $this->target_folder.'/'.$base_filename.'.'.str_pad($splitnum, 3, "0", STR_PAD_LEFT);
if(!$fw = fopen($piece_name,"w")) {
die("Erro para abrir o arquivo $piece_name para leitura. Confira as permições da pasta de destino.");
}
while (!feof($handle) and $splitnum < 999) {
if($current < $piece) {
if($content = fread($handle, PWS_file_splitter::BUFFER)) {
if(fwrite($fw, $content)) {
$current += PWS_file_splitter::BUFFER;
} else {
die("Erro, o script não possui permissão de escrita na pasta destino.");
}
}
} else {
fclose($fw);
$current = 0;
$splitnum++;
$piece_name = $this->target_folder.'/'.$base_filename.'.'.str_pad($splitnum, 3, "0", STR_PAD_LEFT);
$fw = fopen($piece_name,"w");
}
}
fclose($fw);
fclose($handle);
}
public function change_file_name($new_file_name){
$this->file_name = $new_file_name;
}
public function change_target($new_target){
$this->target_folder = $new_target;
}
public function change_piece_size($new_piece_size){
$this->piece_size = $new_piece_size;
}
}
Agora veja alguns exemplos de como utilizar essa classe:
//ex01: $my_splitter = new PWS_file_splitter("anjos-resgate.rar","downloads",20); //ex02: $my_splitter->change_target("baixar"); $my_splitter->split_now(); //ex03: $my_splitter->change_piece_size(10); $my_splitter->change_file_name("2012 fim dos tempos.rar"); $my_splitter->change_target("baixar-2012"); $my_splitter->split_now();
Dividir arquivos em várias partes Exemplo 01:
No exemplo 01 eu instancio a classe PWS_file_splitter em um objeto chamado $my_splitter, note que essa classe recebe três parametros quando você monta ela, o primeiro parâmetro é o nome do arquivo que será dividido, o segundo é a caminho destino (pasta) para onde o arquivo dividido deve ser salvo, já o terceiro parâmetro diz respeito ao tamanho médio em megabytes que cada parte deve possuir.
Então o que eu fiz foi informar a classe que eu tenho um arquivo chamado anjos-resgate.rar que se encontra na mesma pasta do script e que ele deve salvar os arquivos divididos em uma pasta chamada downloads – caso não exista, esse caminho será criado – e por fim informei que quero cada parte em pedaços de 20 mb cada.
Dividir arquivos em várias partes Exemplo 02:
No exemplo 02, eu aproveitei o objeto instanciado no exemplo 01, a saber $my_splitter, e invoquei dois métodos dele, o change_target passando como parâmetro o valor “baixar”, isso fará que o objeto salve as partes do arquivo em uma nova pasta chamada baixar. Para que o objeto divida o arquivo e crie as partes, de fato, eu invoquei o método split_now. Veja que o script irá ler o arquivo anjos-resgate.rar novamente e dividir ele em várias partes, salvando essas partes no novo caminho que informei, ou seja “baixar”
Dividir arquivos em várias partes Exemplo 03:
No exemplo 03, eu aproveitei novamente o objeto instanciado em $my_splitter e invoquei alguns métodos, primeiro o split_piece_size, aqui eu mudei o tamanho que antes era 20 para 10mb, ou seja, agora ele vai dividir as partes em pedaços de cerca de 10 megabytes cada. Depois eu invoquei o método change_file_name passando como parâmetro o valor “2012 fim dos tempos.rar”, isso informa ao script que agora é para dividir outro arquivo e não o anjos-resgate.rar. Depois disso eu mudei novamente o caminho destino para savar as partes com o método change_target passando o valor “baixar-2012″. Por fim invoquei o método split_now para executar a tarefa.
Como pode ser visto essa class em php nos permite dividir arquivos em vários pedaços no servidor remoto, mas após baixar as partes divididas como unir elas? Bem, há vários programas que fazem isso, mas você pode utilizar HJ Split para unir as partes em um único arquivo.
take care!









