Jump to content
Rafacharkman

Duvida sobre download automático em PHP

Recommended Posts

Alguém sabe me dizer como que eu faço para o PHP solicitar um download automaticamente dentro de um loop? tentei usar o header() juntamente com o readfile() porém não estou conseguindo pois o 1ª download trava o loop. (algo como aqueles gerenciadores de download do MEGA ou se possível zippar e baixar)

 

 

Share this post


Link to post
Share on other sites

Download dentro de loop não vai funcionar. Você deve usar a opção de zippar e baixar tudo no final.

 

Segue trecho do meu código para fazer download em zip de uma pasta (na qual deve gravar os arquivos antes).

Está dentro de classe, é só tirar os private e os $this-> se não usar classes no seu código.

//PASSE O CAMINHO DA PASTA COM OS ARQUIVOS E O CAMINHO DO ZIP A SER CRIADO.

        private function addzip($source, $destination)
        {
            $files_to_zip = glob($source . '/*');
            $this->create_zip($files_to_zip, $destination);
        }


private function create_zip($files = array(), $dest = '', $overwrite = false)
        {
            if(file_exists($dest) && !$overwrite)
            {
                return false;
            }
            if(($files))
            {
                $zip = new ZipArchive();
                if($zip->open($dest, $overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true)
                {
                    return false;
                }
                foreach($files as $file)
                {
                    $zip->addFile($file, basename($file));
                }
                $zip->close();
                return file_exists($dest);
            }
            else
            {
                return false;
            }
        }

 

COMO USEI PARA GERAR O ZIP E BAIXAR, APÓS TER A PASTA COM OS ARQUIVOS;


 

$this->addzip(APP.DS.'webroot'.DS.'nfes'.DS.'zip_'.$cnpj.str_replace('-', '', $in.$fi), APP.DS.'webroot'.DS.'nfes'.DS.'zip_'.$cnpj.str_replace('-', '', $in.$fi).'.zip');


header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"zip_".$cnpj.str_replace('-', '', $in.$fi).".zip\"");
echo readfile(APP.DS.'webroot'.DS.'nfes'.DS.'zip_'.$cnpj.str_replace('-', '', $in.$fi).'.zip');

 

Share this post


Link to post
Share on other sites

Vlw robson o/
Só que me veio outra duvida, como eu faço por exemplo para adicionar um arquivo que esteja armazenado em uma string? (no caso uma imagem que esteja em texto no banco de dados ou vindo de um link externo)
file_get_contents() já é o suficiente? como faço? Tentei aqui mas não funcionou, parece que ele só lê diretórios =/

 

@EDIT 

Consegui resolver, vou deixar aqui abaixo para quem quiser consultar

<?php
//cria a função ziparchive(). 
$zip = new ziparchive();		

//Caso o arquivo exista somente o acessa, caso não exista cria o arquivo
if(file_exists('./zipfile.zip')) {
		$zip->open('./zipfile.zip'); 
	} else { 
		$zip->open('./zipfile.zip', ziparchive::CREATE);
	}

//Se o arquivo estiver no diretório ou computador...
$zip->addFile('./img.jpg', $newName);

//se o arquivo estiver contido em uma string...
$img = file_get_contents('https://...');
$zip->addFromString('imagem.jpg',$img);

//fecha a solicitação '$zip->open'
$zip->close();

//caso queira enviar uma solicitação de download ao cliente, checa se o arquivo foi criado e faz download
//NOTA: as vezes dependendo do tamanho do arquivo, pode demorar ao mesmo concluir e o criar
//NOTA2: unlink() exclui o arquivo criado do servidor
if(file_exists('./zipfile.zip')){
  header('Content-Type: application/zip');
  header('Content-Disposition: attachment; filename="zipfile.zip"');

  readfile('./zipfile.zip');
  unlink('./zipfile.zip');
}

 

Share this post


Link to post
Share on other sites

Apareceu um novo problema kk'
o ziparchive() retornou um erro quando o tamanho do arquivo passou de 256MB, tem como converter ele para algo como ziparchive64()? To pesquisando porém não encontro nada a respeito... falam que o limite vai até 4GB mas não sei como fazer isso...

 

@EDIT 

eu descobri oque era, na verdade era a memória que ficou cheia pelo uso do addFromString()

Citar

Caso você ainda queira usar o PHP ZipArchive , existem algumas coisas que você pode fazer para evitar certas limitações do servidor / sistema operacional:

  • Memória Embora possa parecer óbvio no seu caso, tenho visto muitos exemplos de como usar o ZipArchive que usam addFromString para adicionar um novo arquivo ao arquivo. NÃO! Isso irá alocar memória para abrir o arquivo e armazenar seu conteúdo nele, o que fará com que você fique sem memória rapidamente, use addFile . Certifique-se também de liberar toda a memória de que não precisa.

  • Tempo de execução Aumenta o tempo máximo de execução do seu script, seja pelo php.ini ou com ini_set (por exemplo, ini_set('max_execution_time', 600);para ter um tempo máximo de execução de 10min)

  • Identificadores de arquivos Alguns sistemas operacionais têm limites quanto ao número de arquivos abertos que podem causar problemas, pois o PHP só adiciona os arquivos ao arquivo zip depois de fechar o arquivo zip. Para evitar problemas com o número de arquivos abertos basta fechar e reabrir o arquivo zip a cada arquivo x (por exemplo, a cada 1000), isso forçará o PHP a compactar e adicionar os arquivos já atribuídos ao arquivo.

  • Tamanho do arquivo Pode haver algumas limitações de tamanho de arquivo do sistema operacional, um arquivo maior também significa que o PHP precisa de mais memória para gerenciá-lo, então eu pessoalmente prefiro usar um tamanho de arquivo máximo após o qual eu apenas abro um novo arquivo zip usando um número de índice . Se o tamanho exato do arquivo não é importante para você, você pode apenas contar o tamanho dos arquivos que vão para o arquivo e depois mudar depois de atingir um certo limite, ou você pode fechar o arquivo todos os arquivos x e verificar seu tamanho no disco para decida se deseja iniciar um novo arquivo ou não (lembre-se, os arquivos só são compactados depois de fechar o arquivo)


Eu pessoalmente gosto de limitar o tamanho do arquivo colocando o tamanho dos arquivos no arquivo e aplicando um fator de compressão provável para ver quando o tamanho máximo do arquivo provavelmente será atingido (arquivos jpg ~ 0.9, arquivos zip = 1, arquivos de texto ~ 0.10, ...) e, em seguida, mude para o próximo volume.

 

Referência: StackOverflow

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By Anderson Maciel
      Boa tarde pessoal,

      Estou quebrando a cabeça para resolver um problema, tenho uma div dinâmica que carrega uma <table> em uma das colunas deveria apresentar o componente Switchery, esta <table> é montada a partir de uma função PHP que faz o select em uma tabela do banco de dados conforme abaixo:
       
      echo '<table class="table table-hover"> <thead> <tr> <th>Nome</th> <th>Agrupamento</th> <th>Ativo</th> </tr> </thead> <tbody>'; foreach($data as $row) { If ($row['ativo'] == 1) {$vativochk = "checked";} else {$vativochk = "";} echo '<tr> <td>'.$row['nome'].'</td> <td>'.$row['agrupamento'].'</td> <td><input type="checkbox" name="ativo_grid" class="js-switch" '.$vativochk.' disabled="disabled"></td> </tr>'; } echo ' </tbody> </table>'; Aqui está o Ajax que chama e retorna atualizando a DIV:
      //funcoes do grid dos graficos function atualiza_grid_graficos() { $.ajax({ type: "POST", url: "hubfuncind.php", data: { id_tabindicadores_paineis: $('#id_tabindicadores_paineis').val(), acao: "gridgraficos" }, success: function(data) { $('#conteudo').html(data); } }); } O retorno vem certinho, mas apenas o componente Switchery está vindo desconfigurado, ou seja vem um checkbox normal (html).

      O que é mais incrível é que neste mesmo formulário mais acima tenho este mesmo componente funcionando normalmente, somente dentro da DIV dinâmica é que fica desconfigurado conforme imagem anexa.

      Será que alguém já passou por isso?

    • By violin101
      Caros amigos membros do grupo, saudações...
       
      Gostaria de tirar uma dúvida com os amigos.
       
      Tenho uma rotina onde consigo efetuar o Download de arquivos para uma pasta dentro do sistema, o que preciso seria mudar o nome do arquivo, por exemplo:
       
      após selecionar  o arquivo criado com o nome de: ESTOQUE.PDF
       
      gostaria de gravar na pasta de upload's com um novo nome, como por exemplo: cliente[1]-estoque.pdf.
       
      Onde poderia fazer essa alteração na rotina abaixo, para gravar o arquivo com um novo nome ?
       
      abaixo posto o fonte da rotina.
      <?php public function anexar() { $this->load->library('upload'); $this->load->library('image_lib'); $upload_conf = array( 'upload_path' => realpath('./assets/anexos'), 'allowed_types' => 'pdf|PDF|doc|DOC|docx|DOCX', // formatos permitidos para anexos de os 'max_size' => 1024, ); //Recebe a variável via POST $validade = $this->input->post('validade'); $this->upload->initialize($upload_conf); foreach ($_FILES['userfile'] as $key => $val) { $i = 1; foreach ($val as $v) { $field_name = "file_".$i; $_FILES[$field_name][$key] = $v; $i++; } } unset($_FILES['userfile']); $error = array(); $success = array(); foreach ($_FILES as $field_name => $file) { if (! $this->upload->do_upload($field_name)) { $error['upload'][] = $this->upload->display_errors(); } else { $upload_data = $this->upload->data(); if ($upload_data['is_image'] == 1) { // set the resize config $resize_conf = array( 'source_image' => $upload_data['full_path'], 'new_image' => $upload_data['file_path'].'thumbs/thumb_'.$upload_data['file_name'], 'width' => 200, 'height' => 125 ); $this->image_lib->initialize($resize_conf); if (! $this->image_lib->resize()) { $error['resize'][] = $this->image_lib->display_errors(); } else { $success[] = $upload_data; $this->load->model('Dados/Dadosclie_model'); $this->Dadosclie_model->anexar($this->input->post('idCli'), $this->input->post('descricao'), $validade, $upload_data['file_name'], base_url().'assets/anexos/', 'thumb_'.$upload_data['file_name'], realpath('./assets/anexos/')); } } else { $success[] = $upload_data; $this->load->model('Dados/Dadosclie_model'); $this->Dadosclie_model->anexar($this->input->post('idCli'), $this->input->post('descricao'), $validade, $upload_data['file_name'], base_url().'assets/anexos/', '', realpath('./assets/anexos/')); } } } if (count($error) > 0) { echo json_encode(array('result'=> false, 'mensagem' => 'Nenhum arquivo foi anexado.')); } else { echo json_encode(array('result'=> true, 'mensagem' => 'Arquivo(s) anexado(s) com sucesso .')); } } ?>  
      Grato,
       
      Cesar
    • By ViniciusRamoa
      Oi! Quando eu comecei a estudar php e logica de programação, é que uma das primeiras coisas que precisamos ter é uma noção exata do que queremos fazer, entao, o que eu estou querendo fazer, eu diria que é bem ousado para um iniciante, mas eu estou estudando e meu único foco é criar um de conteudos simples para meu site, será apenas para uso pessoal, nal tenho interesse em vender, mas iria disponibilizar para download , caso alguém queira, ele irá apenas postar conteúdos, apagar, editar e somente isso, não editará banner, ou layout ou qualquer outra coisa. Quero criar um sistema de loguin e dar permissão para apenas quem tiver o "rank 2" será considerado um adm e poderá postar.
      Nesse campo de postagem, terá apenas os campos de:
      Titulo
      Imagem (thumbnail)
      Link da página  (pois será um post clicavel, como um cardbox que ira redirecionar o visitante para a página destinada apenas àquele  conteudo) 
      Descrição 
      Apenas  isso
      Então, eu estou estudando PHP, no início ainda, mas é possivel eu criar tal ferramente em quanto tempo em média com a experiência que vocês ja possuem? 
      E outra, qual caminho devo seguir? Quero apenas criar o gerenciador de conteudo e sistema de loguin, tem algum "caminho" que eu deva seguir? Tenho que focar mais em x area para atingir o que eu quero e nao focar em y area, pois será perda de tempo? Como eu disse, quero apenas criar isso, e futuramente me aprofundar mais
      Então, possui alguma dica, orientação, link ou qualquer coisa que possa me ajudar a pelo menos ver qual caminho seguir, levando em conta que estou estudando por conta propria e nao tenho quem me orientar? Obrigado 
    • By Anderson Maciel
      Boa tarde pessoal,

      Estou quebrando a cabeça para resolver um problema, tenho uma div dinâmica que carrega uma <table> em uma das colunas deveria apresentar o componente Switchery, esta <table> é montada a partir de uma função PHP que faz o select em uma tabela do banco de dados conforme abaixo:
       
      echo '<table class="table table-hover"> <thead> <tr> <th>Nome</th> <th>Agrupamento</th> <th>Ativo</th> </tr> </thead> <tbody>'; foreach($data as $row) { If ($row['ativo'] == 1) { $vativochk = "checked"; } else { $vativochk = ""; } echo '<tr> <td>'.$row['nome'].'</td> <td>'.$row['agrupamento'].'</td> <td><input type="checkbox" name="ativo_grid" class="js-switch" '.$vativochk.' disabled="disabled"></td> </tr>'; } echo '</tbody> </table>'; Aqui está o Ajax que chama e retorna atualizando a DIV:
       
      function atualiza_grid_graficos() { $.ajax({ type: "POST", url: "hubfuncind.php", data: { id_tabindicadores_paineis: $('#id_tabindicadores_paineis').val(), acao: "gridgraficos" }, success: function(data) { $('#conteudo').html(data); } }); } O retorno vem certinho, mas apenas o componente Switchery está vindo desconfigurado, ou seja vem um checkbox normal (html).

      O que é mais incrível é que neste mesmo formulário mais acima tenho este mesmo componente funcionando normalmente, somente dentro da DIV dinâmica é que fica desconfigurado conforme imagem anexa.

      Será que alguém já passou por isso?

    • By egalauber
      Preciso descobrir qual é o nome do arquivo com a extensão.
      Só sei o início do nome:
       
      pasta "anexos".
      nome_do_arquivo_DAQUI_PRA_FRENTE_NAO_SEI_O_RESTO_DO_NOME_NEM_A_EXTENSAO
       
      Com a função glob eu consigo achar o arquivo, mas o nome completo ainda não.
       
       
      $verifica = glob("anexos/nome_do_arquivo_*");
      if($verifica == true){
         // achei o arquivo e agora preciso pegar o nome completo e a extensão
      } else {
            echo "Arquivo não encontrado";
         }
×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.