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 Anonicah
      Olá preciso de ajuda com esse exercício. Montei até a parte de formulário + validação de javascrip no dreamweaver mas buguei com o resto. O que eu fiz:
       

      <html>
      <head>
      <title> Formulário CPF validado com Java Script </title>
          
          <script language="javascript" type="text/javascript">
      function validar() {
      var cpf = form1.cpf.value;
          
      if (cpf == "") {
      alert('Preencha o campo com seu cpf');
      form1.cpf.focus();
      return false;
      }
          
      }
      </script>
          
          
      </head>
      <body>
      <form name="form1" action="enviar.php" method="post">
      CPF:
      <input name="cpf" type="text"><br /><br />
      <input type="submit"  onclick="return validar()">
      </form>
      </body>
      </html>
       
       
      EXERCÍCIO
      Criar um formulário simples em html com um único campo CPF;
      Fazer uma validação em javascript antes de fazer o post;
      Consumir o WS https://bi.vidaclass.com.br/utils para consultar informações do CPF enviado pelo form;
      Do retorno obtido exibir na tela:
      Nome, email, telefone
      Se tem compra em saude: Sim | Não
      Quantas compras: (5) ex.
      Se tem farma: Sim | Não
      Se tem dependente: Sim | Não
      Qtd. de dependentes: (2) ex.

      Obtem o token para consumir os endpoints;
      https://bi.vidaclass.com.br/auth
      {
          "company_id": 1,
          "username": "webmaster@vidaclass.com.br",
          "password": "Teste20170705"
      }
      Endpoint para consultar o CPF
      https://bi.vidaclass.com.br/utils
      {
          "action": 4,
          "key": {
              "cpf": 25383193820
          }
      }
    • By Luciano Marques
      Então pessoal é o seguinte: Estou tendo problemas para impedir acesso simultâneo no meu projeto. Foi depois de muito pesquisar que vim aqui abrir esse tópico. 
      Enfim, eu até consegui colocar uma teoria em prática que era a de criar uma coluna na tabela `usuarios` com 1 para ativo, e 2 para  inativo. e depois coloquei no topo a condição IF para se 1 já preenchido não permite o login. até ai de boa. o problema vem se o usuário não desloga só fecha a janela. a coluna ainda permanece como ativa 1. mesmo expirando o login, não ocorre o update na base de dados. Se alguém puder me ajudar nessa, preciso concluir esse trabalho ainda essa semana. desde já agradeço 
    • By paulojk
      Como faço essa funçao alguem sabe? Depos que o usuario clica no botao so libera depois de um determinado tempo.
       


    • 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
×

Important Information

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