Link to home
Create AccountLog in
Avatar of Eduardo Fuerte
Eduardo FuerteFlag for Brazil

asked on

Could you point why an Excell file read at browser (js) is obtained at PHP code as a tmp file?

Hi Experts

Could you point why an Excell file read at browser (js) is obtained at PHP code as a tmp file?

Accordingly with:
User generated image
The JS code called (that produces the console showed above):

 
User.prototype.subirLote = function() {
 // Called to upload the file
   console.log('XXXX');
  $("#arquivoLote").trigger("click");
  
  arquivo = $("#arquivoLote").val();
  
// The name is empty
  console.log('Y ' + arquivo);

};

Open in new window


When this PHP code is called:
<? 
//------------------------------------------------------------
    public function subirLote(Request $request){
//------------------------------------------------------------  
      
      $arquivo=$request->file('arquivoLote');
	  
	  
*--- AT THIS POINT THE FILE IS RECEIVED AS: C:\xampp\tmp\php6669.tmp (OR SOMETHING LIKE)
file_put_contents('debug.log', 'Arquivo = '. $arquivo.PHP_EOL , FILE_APPEND);
*-----------------------------------------------------------------------------

      Config::set('excel.import.heading', 'slugged_with_count');
      Config::set('excel.import.startRow', 1);

      try{

        $arquivoUrl = AzureStorage::saveFile($arquivo,'arquivos');
    
        $planilha = Excel::selectSheets('Participantes')->load($arquivo)->toArray();
      
        $validacao = $this->validarArquivo($planilha);
        

        if(!$validacao["valido"])
		{  
   
          return response()->json(new Resultado(false,"",$validacao));
        }
        
        $this->processarLote($planilha);
    
        $saida = array (
          "mensagem"=>"<div class='alert alert-success text-center'><strong>Sucesso:</strong> Arquivo processado com sucesso!</div>",
          "valido"=>true
        );

      } catch (\Exception $e) {
        Debugbar::info($e);
        Log::error($e);
        

        $saida = array (
          "mensagem"=>"<div class='alert alert-warning text-center'><strong>Informação:</strong> 002 Arquivo de participantes com formato inválido.<br />Por favor, verifique-o antes de continuar</div>",
          "valido"=>false
        );
      }
      return response()->json(new Resultado(false,"",$saida));
    }
 ?>

Open in new window


User generated image
The code is under Laravel with Excel Libraries, I don't know if this error is related with this fact.

Thanks in advance
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Hey Eduardo,

Based on your previous question, I would guess that the code you have in Laravel is never told to save the file anywhere - you just request that the file is downloaded by the browser.

Usually, when you do this in PHP, the system just temporarily stores the file before sending it to the browser, which is why you get a tmp filename. The idea behind this is that at some point after the user has downloaded the file, there is no longer a need for it on the server, and the tmp folder can be cleaned up.
When you upload a file to PHP, that is the default behavior (to put it into the temp folder). The reason for this is because you don't know if that file is bad. For example, let's say that instead of uploading an Excel file, someone uploads their own PHP script. If PHP put that script into a web-accessible folder instead of putting it into temp first, then that hacker could then call the PHP script and take over your system.

By putting it into temp first, your PHP code has an opportunity to look at the file and decide where it should go or if it should be deleted, etc...
Avatar of Eduardo Fuerte

ASKER

Hi

Thank you for the replies.

Could you suggest a workaround here to make the Excel sheet to be downloaded?
To make it downloadable, you can either:

1. Put the file into a web-accessible folder and give the user a link. This -can- be dangerous unless all users are equally trusted. Otherwise, if person A shares that link with person B, then person B can download the file, too.

2. Use PHP to read the file and push it to the user as a download. The readfile() documentation page has some sample code for doing this:
https://www.php.net/manual/en/function.readfile.php

I'd recommend #2 so you can implement security controls as necessary.
By doing that is it necessary to modify the JS code first to save the Excel sheet at another location ?

The only way a user could upload the file is by using the browser.
No, the JS code doesn't control the location, and it SHOULD NOT ever have anything to do with the final location. Javascript runs completely on the client side and can be easily modified or hacked. PHP should be the one controlling the file's location.
In the meanwhile I found the JS code used to upload:

    hotsite.InitFileUpload("arquivoLote", "/admin/user/subirLote", pars, resultBatchUpload, failBatchUpload);
      $("#arquivoLote").change(function () {
        
        console.log('file to be upload...');
        
        
          if (jqXHRData) {
              jqXHRData.submit();
          }
          return false;
      });

Open in new window


The console.log is fired.

It seens that the file to be uploaded remains at:  /admin/user/subirLote

Based on your previous reply, where PHP is going to find the Uploaded file, so?

/admin/user/subirLote  is not existent at C:\XAMPP\
I'm sorry, but I don't quite understand what you were saying in that last comment.

"Hotsite" sounds like a 3rd party plugin. I don't really know the data structure that it is sending, so I can't tell you what PHP to use to read the folder name. Maybe there is documentation from wherever you got "Hotsite" from?
It's not a 3rd part plugin

Here is the page complete code:
<script>
  var jqXHRData;
  $(document).ready(function () {
      var pars = {
                  _token:$('input[name="_token"]').val(),
              };

      var resultBatchUpload = function (data) {
        
                  //EF
              console.log('ZZZZ');
        
        
        if (!data.result.erro) {
            //$('#visualiza').html(data.result.retorno.retorno);
            
              //EF
              console.log('OK');
            
            $('#visualiza').html(data.result.retorno.mensagem);
            
               //EF
              //console.log($('#visualiza').html(data.result.retorno.mensagem));
            
            $('#visualiza').show();
            if(data.result.retorno.valido){
              $('#btnImportar').show();
              $('#arquivoImportar').val(data.result.retorno.arquivo);
              
              //EF
              console.log('Z1111');
              console.log($('#arquivoImportar').val());
              
              
            } else {
               
               console.log('Z2222');
              $('#btnImportar').hide();
              $('#arquivoImportar').val('');
            }
            return true;
        } else {
            
            //EF
            console.log('PPPP  Error');
            
          hotsite.openModalCustom("Erro",'Erro ao subir lote.', "Entendi", "error");
          return false;
        }
      };

      var failBatchUpload = function (data) {
          if (data.files[0].error) {
              hotsite.openModalCustom("Erro",'Erro ao subir a lote.', "Entendi", "error");
              return false;
          }
      };

      hotsite.InitFileUpload("arquivoLote", "/admin/user/subirLote", pars, resultBatchUpload, failBatchUpload);
      $("#arquivoLote").change(function () {
        
        console.log('arquivo para upload...');
        
        arquivo = $("#arquivoLote").val();
        
        console.log('Y ' + arquivo);
         
         
          if (jqXHRData) {
              jqXHRData.submit();
          }
          return false;
      });
  });
</script>
<!-- Modal -->
<div class="modal fade" id="mBatchUser" tabindex="-1" role="dialog" aria-labelledby="mBatchUserLabel">
  <div class="modal-dialog modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="mBatchUserLabel">Lote de Participantes</h4>
      </div>
      <div class="modal-body">
        <div class='row'>
          <div class='col-md-12 text-center'>
            <a href='/content/templates/loteparticipantes.xlsx' class='btn btn-warning'><i class="fas fa-download" aria-hidden="true"></i> Obter Modelo</a>
            <button id='btnLote' class='btn btn-primary' onclick='hotsite.user.subirLote();'><i class="fas fa-upload" aria-hidden="true"></i> Carregar Lote de Participantes</button>
            <input type='file' id='arquivoLote' name='arquivoLote' style='display:none;'/>
            <input type='hidden' id='arquivoImportar' name='arquivoImportar'/>
          </div>
        </div>
        <br/>
        <div class='row'>
          <div class='col-md-12'>
            <div id='visualiza' style="height:400px;overflow:auto;display:none;">
            </div>
          </div>
        </div>
      </div>

      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal"><i class="fas fa-times" aria-hidden="true"></i> Fechar</button>
        {{--  <button id='btnImportar' onclick='hotsite.user.processarLote();' type="button" class="btn btn-primary"><i class="fas fa-cloud-upload-alt" aria-hidden="true"></i> Importar</button>  --}}
      </div>
    </div>
  </div>
</div>

Open in new window


And the console reply:
User generated image
It seens that the file to be uploaded doesn't seen to be valid.
All we're seeing is the initial upload form, which seems to upload the file correctly. What do you expect the system to do with that file? How are you trying to access it afterwards?
Sorry....

After talking with company's people I found was trying to upload a wrong kind of Excel sheet....

No JS must to be adjusted.

The code uses some Azure code on its process, also (still misterious how it deals with, later I'm going to better check this part)

Now the things are going...
The PHP code is:

    public function subirLote(Request $request){

      $arquivo=$request->file('arquivoLote');

      Config::set('excel.import.heading', 'slugged_with_count');
      Config::set('excel.import.startRow', 1);

      try{
	  
        $arquivoUrl = AzureStorage::saveFile($arquivo,'arquivos');
		
        $planilha = Excel::selectSheets('Participantes')->load($arquivo)->toArray();
        
       
        $validacao = $this->validarArquivo($planilha);

        if(!$validacao["valido"])
          return response()->json(new Resultado(false,"",$validacao));

        $this->processarLote($planilha);

        $saida = array (
          "mensagem"=>"<div class='alert alert-success text-center'><strong>Sucesso:</strong> Arquivo processado com sucesso!</div>",
          "valido"=>true
        );

      } catch (\Exception $e) {
        Debugbar::info($e);
        Log::error($e);

        $saida = array (
          "mensagem"=>"<div class='alert alert-warning text-center'><strong>Informação:</strong> Arquivo de participantes com formato inválido.<br />Por favor, verifique-o antes de continuar</div>",
          "valido"=>false
        );
      }

      return response()->json(new Resultado(false,"",$saida));
    }

Open in new window



$arquivo is obtained by the browser.

Could you give me any guidance on how Azure interacts here?
No. AzureStorage is not a standard PHP library. You would have to look at the code for that library to know how it works. There might be a header / comment block that shows you where to find the documentation for it.
ASKER CERTIFIED SOLUTION
Avatar of Eduardo Fuerte
Eduardo Fuerte
Flag of Brazil image

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Thank you for the guidance.