8

I'm using laravel 4.2 and currently I don't how to save a csv file into public\csv\ directory using AJAX. I'm still finding some answers. Maybe someone can help me with this.

Here's my code:

In blade view:

 {{Form::open(['route' => 'file_upload', 'files' => true, 'id' => 'upload_form', 'method' => 'POST'])}}
    {{Form::file('csv_upload', ['id' => 'uploaded_file', 'accept' => 'text/csv'])}}
    {{Form::submit('submit', ['class' => 'btn btn-primary btn-xs', 'id' => 'upload'])}}
 {{Form::close()}}

Javascript Ajax:

var ajax_ready = 1
var token = {{Session::get('_token')}}

if($.type(originalOptions.data) === 'string') {
              options.data = originalOptions.data+"&_token="+token;
 }else if($.type(originalOptions.data) === 'object') {
         //Here I got a new error
 }else{
     options.data = $.param(($.extend(originalOptions.data, {'_token':mmad_token})));
 }

 options.url = originalOptions.url.slice(0,originalOptions.url.indexOf("?_token="));

   if (ajax_ready!=1){
              jqXHR.abort();
   }
  ajax_ready = 0;
});
$('form#upload_form').on('submit', function(e){
    e.preventDefault();
    var uploadFile =  $('#uploaded_file');

    var ext = $("input#uploaded_file").val().split(".").pop().toLowerCase();
    var file = $('input[name="csv_upload"]').val();

    if($.inArray(ext, ["csv"]) === -1) {
             alert("Please upload a .csv file!");
             return false;
    }

     var csv = uploadFile[0].files;
     var form = new FormData(this);

     var csvFile = {lastModifed: csv[0].lastModified, fileName: csv[0].name, size: csv[0].size, fileType: csv[0].type};

      $.post('{{ URL::route("file_upload") }}?_token={{Session::token()}}',{
           data: form
      }).done(function(response){

      });

});

PHP:

public function upload_csv()
{
    $inputs = Input::all();

    $csvFile = $inputs['data']['fileName'];

    $path = public_path().DIRECTORY_SEPARATOR.'csv'.DIRECTORY_SEPARATOR;
    $path2 = public_path('csv/');

    if(is_dir($path2))
    {
        @move_uploaded_file($csvFile, $path2.$csvFile); //This line can't move the uploaded files in my desired directory
    }

    return json_encode(['success' => 1, 'description' => 'Successfully Upload File']);

}

This code below does work when not using AJAX:

  if(Input::hasFile('csv_upload'))
    {
        $file = Input::file('csv_upload');

        $originalFilename = $file->getClientOriginalName();

        $rules = ['csv_upload' => 'required|file:csv'];

        $validate = Validator::make(['csv_upload' => $file], $rules);

        if($validate->fails())
        {
            return json_encode(['error' => 1, 'description' => 'File must be in .csv format']);
        }

        $path = public_path('/csv/');

        if(!file_exists($path))
        {
            mkdir($path);
        }
     }

Console.log of csv

CSV DATA

aldrin27
  • 3,407
  • 3
  • 29
  • 43

4 Answers4

5

You can not move file because when you submit form with ajax file is not being sent with ajax,For sending file you have to send file with FormData() javascript Object.

If you check in upload_csv controller by putting print_r($_FILES); you will get empty array.

So use FormData on client side for appending file, then try agian. You aren't getting error beacuse you have used php Error Control Operators likes@move_uploaded_file($csvFile, $path2.$csvFile);.

if you need working example then tell me i will give it to you.

Code For Your Help: 1. In blade view:

  <script type="text/javascript">
     $('form#upload_form').on('submit', function(e){
        e.preventDefault();
        var uploadFile =  $('#uploaded_file');

        var ext = $("input#uploaded_file").val().split(".").pop().toLowerCase();
        var file = $('input[name="mmad_csv_upload"]').val();

        if($.inArray(ext, ["csv"]) === -1) {
                 alert("Please upload a .csv file!");
                 return false;
        }
        var csv = uploadFile[0].files;
        var formData = new FormData($(this)[0]);
        formData.append('uploaded_file', $("#uploaded_file")[0].files[0]);
        formData.append('lastModifed', csv[0].lastModified);
        formData.append('fileName', csv[0].name);
        console.log(formData);


        $.ajax({
        url: '{{ URL::route("file_upload") }}',
        type: 'POST',
        data: formData,
        async: true,
        cache: false,
        contentType: false,
        processData: false,
        success: function (returndata) { //alert(returndata); return false;

        }
        });      

    });
 </script>

2.Controller

public function file_upload(Request $request)
{
    $inputs = Input::all();
    $csvFile = $inputs['fileName'];


    $path = public_path().DIRECTORY_SEPARATOR.'csv'.DIRECTORY_SEPARATOR;
    $path2 = public_path('/csv/');
    if(is_dir($path2))
    {
        $success = $request->file('uploaded_file')->move($path2, $csvFile);
    }
    return json_encode(['success' => 1, 'description' => 'Successfully Upload File']);

}
Vishal Patel
  • 1,715
  • 16
  • 26
  • Can you please give me? I want to fetch data files using `Input::file('filename')` – aldrin27 Oct 26 '15 at 09:30
  • I have edited a my answer and added code.Please check. – Vishal Patel Oct 26 '15 at 10:25
  • Okay i'll try this tomorrow. – aldrin27 Oct 26 '15 at 11:19
  • It say's `Error: Illegal invocation`. – aldrin27 Oct 26 '15 at 22:42
  • Note. This is not Laravel 5.1, the version I'm using is 4.2 – aldrin27 Oct 27 '15 at 01:59
  • I know now why my laravel code didn't work it's because of `AJAX PREFILTER` – aldrin27 Oct 27 '15 at 03:34
  • 1
    you have used a $.post() function of jQuery instead of you have to use $.ajax function for formdata() have you changed that one. You are getting Illegal invocation because jQuery is trying to serialize the jQuery object for $.post, and it can't. It's probably trying to call a string method, and is passing it a jQuery object as context, thus causing the error. – Vishal Patel Oct 27 '15 at 04:45
  • I've just delete the `$.ajaxPrefilter`. It solves my problem but I want to have `$.ajaxPrefilter` so I tried to manipulate it to fully solved my problem. It's in my question. – aldrin27 Oct 28 '15 at 05:28
0

To move the uploaded file to a new location, you should use the move method. This method will move the file from its temporary upload location (as determined by your PHP configuration) to a more permanent destination of your choosing:

Input::file('fileName')->move($destinationPath, $fileName);

If you need additional validations, you can check it at http://laravel.com/docs/5.1/requests#files

Somnath Muluk
  • 55,015
  • 38
  • 216
  • 226
0

Default AJAX POST does not support file uploads. Use jQuery Form to upload files successfully. Full documentation of file upload at http://malsup.com/jquery/form/#file-upload

Below my example of a recentlty build script... My Controller uploads the files to S3, but is easy to be implemented with local storage.

var progress = function(event, position, total, percent) {
    $(".progress-bar").width(percent + '%');
    $(".progress-bar").html(percent + '%');
    if(percent > 50) {
        $(".progress-bar").css('color','#fff');
    }
    if(percent == 100) {
        setTimeout(function(){
            $(".progress").html('<span class="processing-msg">Processing... Please be patient!</span>');
            $(".processing-msg").fadeIn('slow');
        }, 1000);
    }
}

var success = function(data) {
    var obj = $.parseJSON(data);
    $("#"+obj.hidden, parent.document).val(obj.filename);
    var src = 'https://s3.amazonaws.com/spincms'+obj.path+'thumb_'+obj.filename;
    $("#uploaded-"+obj.hidden, parent.document).html('<img class="img-circle uploaded-img" src="' + src + '">');
    $(".progress").html('<span class="processing-msg-next">File has been uploaded and processed. Do not forget to submit the form!</span>');
}

var options = {
    target: '#output',
    uploadProgress: progress,
    success: success,
    resetForm: true
};

$(document).on('click', "#upload-now", function(e) {
    $(".progress").html('<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>');
    if($("#upload-form input[type=file]")[0].files.length == 0) {
        $(".progress").html('<span class="processing-msg-next">No file selected!</span>');
        return false;
    } else {
        var name = $("#upload-form input[name='name']").val();
        var token = $("#upload-form input[name='_token']").val();
        var file_name = $("#upload-form input[type=file]")[0].files[0].name;
        $("#upload-form").ajaxSubmit(options);
        }
    }
});
Alvin Bakker
  • 1,456
  • 21
  • 40
  • What's the solution than @aldrin27? The whole idea for stackoverflow is to share the outcome and/or mark an answer as solution... Thanx – Alvin Bakker Oct 28 '15 at 02:56
0

Since you are using jQuery you can use the form plugin as it will make things much more easier for you to work with for example , this is the jquery part that you will use :

$(document).ready(function() { 
    // bind 'myForm' and provide a simple callback function 
    $('#upload_form').ajaxForm(function() { 
        alert("Your file has been uploaded, thanks"); 
    }); 
}); 

and in your controller you can code it like :

pubilc function postUpload()
{
    $success = false;
    if(Request::ajax())
    {
        if(Input::hasFile('csv_upload'))
        {
            $file = Input::file('csv_upload');
            if(!File::isDirectory(storage_path('csv'))) {
                File::createDirectory(storage_path('csv'));
            }

            $file->move(storage_path('csv'), $file->getClientOriginalName());
            // now your file is on app/storage/csv folder
            $filePath = storage_path('csv/'.$file->getClientOriginalName());
            $success = true;
        }   
    }


    return Response::json(['success'=>$success]);
}
Zaher
  • 1,120
  • 7
  • 18