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 danilo759
      Tenho uma tabelinha de programas para uma rádio... está da seguinte forma.

      titulo
      data (YYYY-MM-DD)
      hora (00:00:00)

      Minha consulta, mas não retorna o programa da hora corrente. O que eu fiz de errado?
      SELECT * FROM programas WHERE data = CURDATE() AND hora = CURTIME() LIMIT 1
    • By Ro_JnR
      Estou tentando a semanas resolver um problema, consumir uma API e verificar se o campo no banco está vazio, se estiver faz insert se não faz update.
      Até aí tudo bem, agora não consigo passar do meu select para o banco, ele da erro.
       
      Segue o código:
       
      <?php

          require_once("db.class.php");
          
          $url = "https://servicodados.ibge.gov.br/api/v1/localidades/distritos";
              $ch = curl_init($url);
              curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
              curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
              $resultado = json_decode(curl_exec($ch));
              foreach ($resultado as $cidades) {
                  $nome = $cidades->nome;
                  $stmt = $conn->prepare("SELECT name FROM cidades WHERE name=?");
                  $stmt->bind_Param(':name', $nome);
                  $stmt->execute();
                  $stmt->bind_result($resultSelect);
                  $stmt->fetch();
                  if(!$stmt->execute()){
                      print_r($stmt->errorInfo());
                  }
              } 

      ?>
       
      Código do banco:
       
      $conn = new PDO("mysql:host=localhost;dbname=exercicio", "root", "");
      //"sqlsrv:Database=dbphp7;server=localhost\SQLEXPRESS;ConnectionPooling=0", "sa", "root");
      $stmt = $conn->prepare("SELECT * FROM cidades ORDER BY nome");
      $stmt->execute();
      //fetchALL basicamente faço while do mysqli
      $results = $stmt->fetchALL(PDO::FETCH_ASSOC);
       
      Print do erro:

       
      Tenho um outro exercicio que fiz bem parecido, consumi a API de estados e inseri no banco de dados, esse funcionou normalmente.
      Alguém poderia me dar uma luz, não sei mais o que fazer.
      Era para ser simples rsrsrrs.
    • By asacap1000
      Galera me foi solicitado a criação de um servidor web, para disponibilizar serviços para os clientes. O que vocês recomendam?
      Tenho um servidor da DELL com windows 2016. Todo o desenvolvimento será em PHP, Javascript e companhia Ltda com conexão aos bancos de dados Mysql, SQL e ORACLE.
      Já temos um servidor que será desativado porém está utilizando uma versão muito antiga de PHP 5.4 e como base de instalação foi utilizado o WampServer. 
    • By asacap1000
      Galera me foi solicitado a criação de um servidor web, para disponibilizar serviços para os clientes. O que vocês recomendam?
      Tenho um servidor da DELL com windows 2016. Todo o desenvolvimento será em PHP, Javascript e companhia Ltda com conexão aos bancos de dados Mysql, SQL e ORACLE.
      Já temos um servidor que será desativado porém está utilizando uma versão muito antiga de PHP 5.4 e como base de instalação foi utilizado o WampServer. 
    • By dutopfave
      Boa Noite Galera, estou com dúvida em como cria um cadastra de VARIAÇÕES DE PRODUTOS.

      Ex.: Tenho um produto que é um TENIS, ai nele vou criar as VARIAÇÕES, então vou usa COR e TAMANHO.
      COR: preto, verde, azul
      TAMANHO: 39, 40, 41

      até ai blz, porém a duvida é como fazer o cadastrado de combinações de cor e tênis, tipo no banco de dados teria q fica exatamente assim....

      ID | COR | TAMANHO
      ... | preto | 39
      ... | preto | 40
      ... | preto | 41
      ... | verde | 39
      ... | verde | 40
      ... | verde | 41
      ... | azul | 39
      ... | azul | 40
      ... | azul | 41

      alguém tem alguma solução
×

Important Information

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