We help IT Professionals succeed at work.

Could you give me directions on how this JS uploading photo method is running?

Eduardo Fuerte
on
Hi Experts

Could you give me directions on how this JS uploading photo method is running?

-- web page script

<script>
  var jqXHRData;
  $(document).ready(function() {
    ZZZsite.video.filtrar();
    var pars = {
        _token:$('input[name="_token"]').val()
    };

    var resultImageUpload = function (data) {
        if (!data.result.erro) {
            localizacao = data.result.retorno.localizacao;
            $('#url').val(localizacao);
            $('#srcVideo').attr('src', localizacao);
            $("#box-video video")[0].load();
            return false;
        } else {
          ZZZsite.openModalCustom("Erro",'Erro ao subir vídeo.', "Entendi", "error");
          return false;
        }
    };

    var failImageUpload = function (data) {
          if (data.files[0].error) {
              ZZZsite.openModalCustom("Erro",'Erro ao subir vídeo.', "Entendi", "error");
              return false;
          }
    };

// --- DOES THIS PART ASKS TO SAVE ON A PATH (???)
    ZZZsite.InitFileUpload("file", "/admin/videos/salvarVideo", pars, resultImageUpload, failImageUpload);
//----------------------------------------


    $("#file").change(function () {
        if (jqXHRData) {
            jqXHRData.submit();
        }
        return false;
    });
  })
</script>

Open in new window



-- JS script
ZZZsite.prototype.InitFileUpload = function(
  input,
  url,
  pars,
  doneCallbackFunction,
  failCallbackFunction
) {
  "use strict";

  $("#" + input).fileupload({
    url: url,
    formData: pars,
    dataType: "json",
    type: "POST",
    add: function(e, data) {
      jqXHRData = data;
    },
    done: function(event, data) {
      if (
        doneCallbackFunction != undefined &&
        typeof doneCallbackFunction == "function"
      ) {
        doneCallbackFunction(data);
      } else {
        ZZZsite.openModalCustom("Erro", data, "Entendi", "error");
      }
    },
    fail: function(event, data) {
      if (
        failCallbackFunction != undefined &&
        typeof failCallbackFunction == "function"
      ) {
        failCallbackFunction(data);
      } else {
        ZZZsite.openModalCustom("Erro", data, "Entendi", "error");
      }
    }
  });
};

Open in new window



img001



At VideoController I found the method SalvarVideo ... (called at the page)

   public function salvarVideo(Request $request){
        $video=$request->file('file');

        if (!$request->hasFile('file')){
            $resultado=new Resultado(true,"","Nenhum arquivo foi selecionado.");
            return response()->json($resultado);
        } else {			
            $videoUrl = AzureStorage::saveFile($video,'videos');
        }

        $output = array(
            "localizacao" => $videoUrl,
        );

        $resultado=new Resultado(false,"",$output);

        return response()->json($resultado);
    }

Open in new window


After choosing a photo the textbox is filled with a location very unclear.

Since I'm still developing and need to test it, the correct here is to create a defined path to save the photo image file?

Thanks in advance!
Comment
Watch Question

Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
Hi Eduardo,

It looks like we're only seeing a part of the code, but effectively it's uploading your file by making an AJAX request to your server. If you look at this line:

ZZZsite.InitFileUpload("file", "/admin/videos/salvarVideo", pars, resultImageUpload, failImageUpload);

You'll see the "/admin/videos/salvarVideo" bit. That's the URL on the server that the file is being sent to. Where you save the file once it's uploaded will be defined in that part of your code, so you'd need to look at how that's handled.

As for how the textbox is being filled - you haven't shown us that part of the code. It looks like your script is using another plugin (fileupload()), and I'm guessing that defines the behaviour of the input itself
Eduardo FuerteDeveloper and Analyst

Author

Commented:
Hi Chris!

Our messages crossed (when I was updating the question)... I'm better checking your hints...

The way an image is choosed at web page:

 img002
The textbox is automatically filled (it's disabled all the time)

And Azure is used to save the video...
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
Right. Now I can see the controller method. When a file is uploaded, that method is called and your uploaded file is saved to your Azure account (Microsoft's Cloud Storage):

$videoUrl = AzureStorage::saveFile($video,'videos');

Once that's done, your method returns the location that it's been saved to (on Azure):

$output = array(
    "localizacao" => $videoUrl,
);
$resultado=new Resultado(false,"",$output);
return response()->json($resultado);

Open in new window

And the data that is returned is then used to populate your textbox:

localizacao = data.result.retorno.localizacao;
$('#url').val(localizacao);

Open in new window

Eduardo FuerteDeveloper and Analyst

Author

Commented:
Yes...

Since I'm "cloning" this functionality to save on Vitrine (photos)  It's a matter of recriate another controller with an analog method to save the photos at Azure...

Maybe during the tests phase a local path could replace the save place, (Not necessary)
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
Yeah - you can create new controller method and change the storage location to whatever you like (local for testing / Azure for production).
Eduardo FuerteDeveloper and Analyst

Author

Commented:
So I created VitrineController.

By using a local folder would be a better choice to check the operation success, since by now I don't have direct access to Azure...

Could you please to suggest maybe a  Laravel class to save on a local folder  to replace this?

$vitrineUrl = AzureStorage::saveFile($vitrine,'vitrines');

Open in new window

Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
Laravel has built in classes to work with your storage, so it will partly depend on how you've configured that. The options are configured in config/filesystems.php.

To save an uploaded file, you'd do something like this:

$path = Storage::putFile('images', $request->file('file'));

This will store your uploaded file into an images subfolder within your local folder (app/storage by default). It will automatically generate a file name and set the $path variable to that. You can override the automatic name if you'd prefer by passing in a name.

You can read all about the Laravels file storage system here -> https://laravel.com/docs/6.x/filesystem
Eduardo FuerteDeveloper and Analyst

Author

Commented:
Chris

I had to return back:

img003

Since I created a similar VitrineController at the same location...

img004
I don't know if routes has participation on the proccess:

/* Vídeos */
Route::get('/videos', 'VideoController@index')->middleware('cadastro')->middleware('auth');
Route::get('/videos/{type}/filtrar', 'VideoController@filtrar')->middleware('cadastro')->middleware('auth');
Route::post('/videos/watched', 'VideoController@watched')->middleware('cadastro')->middleware('auth');
Route::get('/videos/sugestao', 'VideoController@sugestionIndex')->middleware('cadastro')->middleware('auth');
Route::post('/videos/sugestao', 'VideoController@sugestion')->middleware('cadastro')->middleware('auth');

/* Vitrine  EF 2020 */
Route::get('/vitrine',['uses'=>'VitrinesController@index'])->middleware('cadastro');
Route::get('/vitrine/{id}',['uses'=>'admin\VitrineController@obter'])->middleware('cadastro');
Route::get('/vitrine/{id}/obter',['uses'=>'admin\VitrineController@obter'])->middleware('cadastro');
Route::post('/vitrine/salvarescolha',['uses'=>'VitrinesController@salvarEscolha'])->middleware('cadastro');

Open in new window



The VideoController runs perfectly...

Could you check?
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
Looks like you have a typo in your controller name. You have an extra s. It should be VitrineController, not VitrinesController

Route::post('/vitrine/salvarescolha',['uses'=>'VitrineController@salvarEscolha'])->middleware('cadastro');

Also, you route is defined as /vitrine/salvarescolha, but the URL giving you an error looks like you're trying to access it at vitrine\salvarVitrine
Eduardo FuerteDeveloper and Analyst

Author

Commented:
I'm going to check...

Amazingly it seens a jquery error

img005
Eduardo FuerteDeveloper and Analyst

Author

Commented:
I have VitrineController under Http\Controllers\Admin\   (Administrative area (where is VideoController also)


And VitrinesController under  Http\Controllers\
(at Participants area)

img006
Eduardo FuerteDeveloper and Analyst

Author

Commented:
Just trying to clarify:

/* Notícias */
Route::get('/noticia',['uses'=>'NoticiasController@index'])->middleware('cadastro');
Route::get('/noticia/{id}',['uses'=>'admin\NoticiaController@obter'])->middleware('cadastro');
Route::get('/noticia/{id}/obter',['uses'=>'admin\NoticiaController@obter'])->middleware('cadastro');
Route::post('/noticia/salvarescolha',['uses'=>'NoticiasController@salvarEscolha'])->middleware('cadastro');


/* Vitrine --  Initally Noticias was the template to construct  on Participants area*/
Route::get('/vitrine',['uses'=>'VitrinesController@index'])->middleware('cadastro');
Route::get('/vitrine/{id}',['uses'=>'admin\VitrineController@obter'])->middleware('cadastro');
Route::get('/vitrine/{id}/obter',['uses'=>'admin\VitrineController@obter'])->middleware('cadastro');
Route::post('/vitrine/salvarescolha',['uses'=>'VitrinesController@salvarEscolha'])->middleware('cadastro');

/* Vídeos -- Now Videos - that remains at admin area is the template - to use the upload feature */
Route::get('/videos', 'VideoController@index')->middleware('cadastro')->middleware('auth');
Route::get('/videos/{type}/filtrar', 'VideoController@filtrar')->middleware('cadastro')->middleware('auth');
Route::post('/videos/watched', 'VideoController@watched')->middleware('cadastro')->middleware('auth');
Route::get('/videos/sugestao', 'VideoController@sugestionIndex')->middleware('cadastro')->middleware('auth');
Route::post('/videos/sugestao', 'VideoController@sugestion')->middleware('cadastro')->middleware('auth');

Open in new window

Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
The jQuery error is a red-herring. The AJAX call is made by jQuery which is why that's showing the error, but the problem is down to your routes.

The error shows that admin/vitrine/salvarVitrine cannot be found. Your routes need to point that URL to the correct controller method:

Route::post('admin/vitrine/salvarVitrine',['uses'=>'admin\VitrineController@salvarEscolha'])->middleware('cadastro');

Now when it looks for the URL admin/vitrine/salvarVitrine, it will fire the salvarEscolha method from the admin\VitrineController controller.

You need to make sure your URL map to the correct Controller and the correct method. You may or may not need admin, depending on whether your routes are setup with a prefix/
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
OK. Look at this:

Route::get('/vitrine',['uses'=>'VitrinesController@index'])->middleware('cadastro');
Route::get('/vitrine/{id}',['uses'=>'admin\VitrineController@obter'])->middleware('cadastro');
Route::get('/vitrine/{id}/obter',['uses'=>'admin\VitrineController@obter'])->middleware('cadastro');
Route::post('/vitrine/salvarescolha',['uses'=>'VitrinesController@salvarEscolha'])->middleware('cadastro');

You have different URLs setup to use different controllers. Some use the VitrinesController and some use the admin/VitrineController. None of the routes are setup to serve urls starting with /admin/

Which controller have you added the new method to?
Eduardo FuerteDeveloper and Analyst

Author

Commented:
Really.

You means:
I couldn't expect the function to run without correctly adding it the the route,

Amazingly the VideoController method salvarVideo is not at routes....
Most Valuable Expert 2018
Distinguished Expert 2019
Commented:
That's correct. When you want to upload an image, you need to give it a URL to send that image to. That will only work if you set up a route to match the URL, so in your Javascript, if you have this:

ZZZsite.InitFileUpload("file", "/admin/vitrine/salvarVitrine", pars, resultImageUpload, failImageUpload);

you will need to set up a route to match that URL, such as:

Route::post('/admin/vitrine/salvarVitrine',['uses'=>'admin\VitrineController@salvarVitrine'])->middleware('cadastro');

Now when an image is uploaded to that URL, it will get POSTed to the salvarVitrine() method in the admin\VitrineController controller.
Eduardo FuerteDeveloper and Analyst

Author

Commented:
It finally runs out!!!
Eduardo FuerteDeveloper and Analyst

Author

Commented:
Chris

Thank you for that other solution very elucidative!!!
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
You're welcome Eduardo