Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Bruno Conte

Fazer upload de xml em um arquivo zip e gravar no banco

Recommended Posts

bom dia.

hoje eu tenho um sistema que faz o upload do xml da nfe e grava todos os campos no bd. O problema e que eu recebo em media 400 nfe's por dia, o que torna o processo muito trabalhoso.

 

Pesquisando e lendo na internet vi a solução de upload de arquivo .zip ou .rar

 

minha duvida e, como eu efetuar o upload de por exemplo 200 nfe e o sistema ja ir gravando tudo no banco.

 

segue abaixo arquivo que uso para gravar dados do xml no banco, isso fazendo upload de apenas uma nota.

 

<?php
include"../includes/conecta.php";
$diretorio = "nfe/";
$upload = $diretorio.$_FILES['nnnfe']['name'];
$nnnfe = $_FILES['nnnfe']['name'];// variavel foto
if(move_uploaded_file($_FILES['nnnfe']['tmp_name'], $upload))
{
	$sql_nfe = mysql_query("insert into nnfe (nfe) VALUES ('$nnnfe')", $db);
	$idimp = mysql_insert_id();
	$sql_puxa_nfe = mysql_query("select * from nnfe where id = '$idimp'", $db);

	$vetor = mysql_fetch_array($sql_puxa_nfe);

	$numeronota = $vetor[nfe];
try
{
   $object = simplexml_load_file( 'nfe/' . $numeronota );
   foreach($object->NFe as $key => $item)
   {
       if(isset($item->infNFe))
       {
	$dataent = $item->infNFe->ide->dSaiEnt;
	$numeronfe = $item->infNFe->ide->nNF;
	$cliente = $item->infNFe->dest->xNome;
	$nomeproduto = $item->infNFe->det->prod->xProd;
	$qtd = $item->infNFe->det->prod->qCom;
	$valorun = $item->infNFe->det->prod->vUnCom;
	$valor = $item->infNFe->det->prod->vProd;
	$comp = $item->infNFe->infAdic->infCpl;
	$data = date("Y-m-d");
	$hora = date("H:i:s");
	$alterado = 'Envio de NFe N°:'.$numeronfe;

	$sql_busca = "select nfe FROM nfe WHERE nfe ='$numeronfe'";
       $exe_busca = mysql_query($sql_busca) or die (mysql_error());
       $num_busca = mysql_num_rows($exe_busca);

       if ($num_busca > 0) {
               echo "Essa NF-e já esta cadastrado.";
			echo"<meta http-equiv=refresh content=3;url='pagina.php?i=uploadnfe.php'>";
               }
	else {


	$sql = mysql_query("insert into nfe (nxml, data, nfe, cliente, nomeproduto, qtd, valorun, valor, comp) VALUES ('$nnnfe', '$dataent', '$numeronfe', '$cliente', '$nomeproduto', '$qtd', '$valorun', '$valor', '$comp')", $db);
	$sql_log = mysql_query("insert into logs (usuario, data, hora, alterado) VALUES ('$usuario', '$data', '$hora', '$alterado')", $db);
	echo "NF-e Cadastrado com Sucesso";
	}


	}

       }
   echo '</table>';
}
catch(Exception $e)
{
   echo $e->getMessage();
}
}
?>

 

so queria poder gravar os dados de varias notas ao mesmo tempo e pensei no zip, agora a duvida e como fazer o upload e ir gravando.

 

att.

Compartilhar este post


Link para o post
Compartilhar em outros sites

http://www.php.net/manual/pt_BR/refs.compression.php

 

Você deve realizar o upload do arquivo zip/rar ou qualquer das compactações listadas acima.

Assim que terminar o upload do arquivo, execute a descompactação do arquivo em alguma pasta.

Após o término de descompactação, realize a leitura de todos os arquivos. A função glob(), por exemplo, seria o método mais fácil de utilizar. Ele retorna um vetor com o nome de todos os arquivos que "casarem" com o pattern especificado.

 

Após a leitura e o retorno do array, realize a iteração sobre o array e utilize normalmente o seu script.

 

Essa é a lógica. Implemente-a, não vejo que possa ter alguma dificuldade em utilizar essas funções. Qualquer dúvida, poste aqui.

Compartilhar este post


Link para o post
Compartilhar em outros sites

esse erro e pq a função nao esta ativada no servidor?

 

Fatal error: Call to undefined function rar_open() in /home3/pedrilim/public_html/carregamento/xmlnfe/uploadrar.php on line 7

 

estou tentando descompactar pelo exemplo e esta dando esse erro:

 

<?php

if(!function_exists("rar_open")){
echo "A funcao rar_open nao esta habilitada";
}

$rar_file = rar_open('xml.rar') or die("Can't open Rar archive");

$entries = rar_list($rar_file);

foreach ($entries as $entry) {
   echo 'Filename: ' . $entry->getName() . "\n";
   echo 'Packed size: ' . $entry->getPackedSize() . "\n";
   echo 'Unpacked size: ' . $entry->getUnpackedSize() . "\n";

   $entry->extract('/xmls/');
}

rar_close($rar_file);

?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

Exato. Neste link há passos da instalação em servidores linux e windows:

http://www.php.net/manual/pt_BR/rar.installation.php

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então utilize zip ao invés de rar. O resultado final é basicamente o mesmo. Entretanto, diferente do rar, não existe nenhuma classe nativa para trabalhar com zip, somente

 

Podem ser utilizadas funções ou classe ZipArchive.

 

Edit----

Alterei para retificar a resposta e evitar dúvidas de futuros usuários.

Conforme mencionado nos posts #9 e #10, o manual PT-BR do PHP está desatualizado, somente a versão em inglês deve ser utilizada como referência.

Compartilhar este post


Link para o post
Compartilhar em outros sites

achei essa aqui na internet, vou tentar usa-la.

 

<?php
if (!extension_loaded('zip')) {
   echo( "Nao esta habilitado php_zip.dll, edite seu php.ini" );
   //no php.ini descomente essa linha, se nao existir basta cria-la: extension=php_zip.dll
   exit;    
}

$dir = dirname(__FILE__)."/";

$zip = new Zip();
$zip->open($dir . "arquivo.zip", ZIP::CREATE);
$zip->addfile($dir . "nome_do_arquivo.extensao", "nome_do_arquivo.extensao");
$zip->close();
?>

Arquivo descompactar.php:


<?php
$zip = new Zip();
$zip->open(getcwd()."/arquivo.zip");
$zip->extractTo("nome_dir");
$zip->close();
?>

 

voce acha que ela me atenderia?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sim, você pode criar uma pastar para descompactar todos os arquivos. Por exemplo, vou separar por data:

$zip = new Zip();
$zip->open(getcwd()."/arquivo.zip");
$zip->extractTo(date('Y-m-d');
$zip->close();

 

Após, utilize a função glob para retornar os arquivos:

/** a função glob aceita padrões ([i]patterns[/i]) para a consulta. Se você for "ler" o comando de busca, seria mais ou menos assim: Dentro do diretório '2012-08-28', arquivos com qualquer nome seguidos de '.xml'. É quase como uma expressão regular, só que em um formato diferente **/
$files = glob('2012-08-28/*.xml');
foreach($files AS $xml) {
   /** aqui você trabalha os arquivos individualmente, utilizando o script que você já possue **/
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sim, eu vi depois. Por algum motivo, olhei rapidamente o manual, foi na versão BR.

http://www.php.net/manual/pt_BR/book.zip.php

 

Não há nada especificado. Eu nunca olho a versão BR por problemas como esse de agora.

 

A mesma página em inglês, possui toda a biblioteca:

http://www.php.net/manual/pt_BR/book.zip.php

Compartilhar este post


Link para o post
Compartilhar em outros sites

Concordo. A versão em PT-BR é bem defasada.

 

Voltando ao problema: a solução com ZIP é bacana, mas qual será o fluxo de informações?

 

Se o volume for alto, sugiro fazer como em um outro post (porém era e-mail): realizar através de tarefas agendadas (cron).

 

Ou seja, "despeja" os arquivos em uma pasta e trata eles aos poucos.

Assim você conseguirá escalonar (se necessário) o serviço facilmente, sem comprometer a performance do sistema que está online. O máximo que pode acontecer é você ter um delay de alguns minutinhos para que a informação fique disponível no sistema. Custo este que no meu ponto de vista vale a pena, em vista dos benefícios que ele traz.

 

@braços e fique com Deus!

Compartilhar este post


Link para o post
Compartilhar em outros sites

vai ser uma media de 200 nfes por dia, que seram lançadas ao final do dia.

 

mais a ideia de receber esses arquivos em uma pasta e com a tarefa cron nao seria nada mal.

 

Mais o php tem alguma função que le e depois apaga o arquivo que ja leu??

 

Por exemplo, ele ler a nota 1 grava no banco e depois exclui aquele arquivo da pasta???

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sim, tem sim.

 

$numArquivosPorCiclo = 10;
$pastaNfs = '/www/notas/';

$atual = 0;
$dir = new DirectoryIterator($pastaNfs);
$regex = new RegexIterator($dir, '@\.xml@i');  // para pegar somente *.xml - mude a extensão conforme necessário

foreach($regex as $file){
 $dom = new DOMDocument('1.0','UTF-8');
 $dom->load( $file->getPathname() );
 // faz o que tem que fazer

 // remove o arquivo
 // sugiro fazer uma copia em algum outro lugar 
 // para caso dê alguma zica, você poder debugar/verificar o ocorrido
 unlink( $file->getPathname() );

 if(++$atual >= $numArquivosPorCiclo){
    break;
 }
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você pode excluir um arquivo através da função unlink().

 

Para remover um diretório, você pode usar a função rmdir. Atente-se ao fato que, para excluir o diretório, ele deve estar vazio, o que torna, para o seu caso, a função um tanto "inútil".

 

Em um script normal, meramente explicativo, baseado no script que eu mencionei acima. Seria o seguinte:

foreach($files AS $xml) {
   //como é um xml, você utilizaria class para tal (SimpleXML por exemplo). Nosso caso é meramente ilustrativo
   $content = file_get_contents($xml);

   $query = mysql_query('INSERT INTO tabela (content) VALUES ("'.$content.'");');

   //retorna false se der algum problema
   if($query !== false) {
      unlink($xml);
   }    
}

 

Ignore o fato de eu utilizar mysql_query(), é meramente ilustrativo. Mas vamos a explicação. Após o INSERT, eu verifico se consulta ocorreu de forma adequada, e então excluo o arquivo.

 

Caso você utilizar PDO, pode usufruir de exceptions, o qual irão tornar seu script muito mais seguro contra falhas e sem necessidade de "grandes" tratamentos.

Compartilhar este post


Link para o post
Compartilhar em outros sites

fiz assim e nao funcionou, so me mostrou um echo que coloquei para testar, ele chegou a ler a 1 nota e nao fez mais nada:

 

<?php

$numArquivosPorCiclo = 10;
$pastaNfs = '/home/pedrilim/public_html/carregamento/nfe/';

$atual = 0;
$dir = new DirectoryIterator($pastaNfs);
$regex = new RegexIterator($dir, '@\.xml@i');  // para pegar somente *.xml - mude a extensão conforme necessário

foreach($regex as $file){
 $dom = new DOMDocument('1.0','UTF-8');
 $dom->load( $file->getPathname() );
 try
{
   $object = simplexml_load_file( $file->getPathname() );
   foreach($object->NFe as $key => $item)
   {
       if(isset($item->infNFe))
       {
	$dataent = $item->infNFe->ide->dSaiEnt;
	$numeronfe = $item->infNFe->ide->nNF;
	$cliente = $item->infNFe->dest->xNome;
	$nomeproduto = $item->infNFe->det->prod->xProd;
	echo $qtd = $item->infNFe->det->prod->qCom;
	$valorun = $item->infNFe->det->prod->vUnCom;
	$valor = $item->infNFe->det->prod->vProd;
	$comp = $item->infNFe->infAdic->infCpl;
	$data = date("Y-m-d");
	$hora = date("H:i:s");
	$alterado = 'Envio de NFe N°:'.$numeronfe;

	$sql_cliente = mysql_query("select * from cliente WHERE nome = '$cliente'", $db) or die (mysql_error());
	$vetor = mysql_fetch_array($sql_cliente);
	$id_tabela = $vetor['tabela'];

	$sql_tabela = mysql_query("select * from tabelaprodutos where id_tabela = '$id_tabela' AND produto = '$nomeproduto'", $db) or die (mysql_error());
	$vetortabel = mysql_fetch_array($sql_tabela);
	$valortabela = $vetortabel['valor'];
	$qtdsoma = number_format($qtd,4,",","");
	$totaltabela = $valortabela * $qtdsoma;
	$totalarmazenar = number_format($totaltabela,0,",",".");

	$sql_busca = "select nfe FROM nfe WHERE nfe ='$numeronfe'";
       $exe_busca = mysql_query($sql_busca) or die (mysql_error());
       $num_busca = mysql_num_rows($exe_busca);

       if ($num_busca > 0) {
               echo "Essa NF-e já esta cadastrado.";
			echo"<meta http-equiv=refresh content=3;url='pagina.php?i=uploadnfe.php'>";
               }
	else {

	if($vetortabel['valor'] == $valorun) {
	$sql = mysql_query("insert into nfe (nxml, data, nfe, cliente, nomeproduto, qtd, valorun, valor, valorunt, valortotalt, comp) VALUES ('$nnnfe', '$dataent', '$numeronfe', '$cliente', '$nomeproduto', '$qtd', '$valorun', '$valor', '$valorun', '$valor', '$comp')", $db);
	$sql_log = mysql_query("insert into logs (usuario, data, hora, alterado) VALUES ('$usuario', '$data', '$hora', '$alterado')", $db);
	echo "NF-e Cadastrado com Sucesso";
	}else{
	$sql = mysql_query("insert into nfe (nxml, data, nfe, cliente, nomeproduto, qtd, valorun, valor, valorunt, valortotalt, comp) VALUES ('$nnnfe', '$dataent', '$numeronfe', '$cliente', '$nomeproduto', '$qtd', '$valorun', '$valor', '$valortabela', '$totalarmazenar', '$comp')", $db);
	$sql_log = mysql_query("insert into logs (usuario, data, hora, alterado) VALUES ('$usuario', '$data', '$hora', '$alterado')", $db);
	echo "NF-e Cadastrado com Sucesso";
	}
	}


	}

       }
   echo '</table>';
}
catch(Exception $e)
{
   echo $e->getMessage();
}
 unlink( $file->getPathname() );

 if(++$atual >= $numArquivosPorCiclo){
    break;
 }
}

?>

 

agora deu o seguinte erro:

 

Warning: mysql_query() expects parameter 2 to be resource, null given in /home3/pedrilim/public_html/carregamento/variosxml.php on line 32

Compartilhar este post


Link para o post
Compartilhar em outros sites

É algum problema com a variável $db. Você chegou a incluir o arquivo conecta.php como inclui no primeiro post?

include"../includes/conecta.php";

Compartilhar este post


Link para o post
Compartilhar em outros sites

tentei rodar para jogar para pasta em zip usando o codigo:

 

<?php
if (!extension_loaded('zip')) {
   echo( "Nao esta habilitado php_zip.dll, edite seu php.ini" );
   //no php.ini descomente essa linha, se nao existir basta cria-la: extension=php_zip.dll
   exit;    
}

$zip = new Zip();
$zip->open(getcwd()."/nfe/nfe.zip");
$zip->extractTo(date('Y-m-d'));
$zip->close();

?>

 

so que deu o seguinte erro:

 

Fatal error: Class 'Zip' not found

 

esse erro e pq a função não esta instalada??? porque meu servidor falou que ja foi ativada.

Compartilhar este post


Link para o post
Compartilhar em outros sites

No lugar de:

$zip = new Zip();

seria:

$zip = new ZipArchive();

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pessoal ali onde o codigo le o xml da pasta e depois o exclui eu tenho uma duvida.

 

fiz uma comparação para que, quando nao tiver o cliente cadastrado ele nao grava no banco de dados. Tem alguma possibilidade por exemplo, se o xml 001 o cliente nao estiver cadastrado ele nao o excluir da pasta??

 

att.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.