how to fix occasional return data when uploading file with ajax - ajax

I have a problem with my code. I created upload file with ajax in Laravel. I am using tutorial from here, and yes it is working. But, it working sometimes.
I have no idea where the problem is. But I have changing max_execution_time in php.ini into 0 value. I also included <code>csrf_token()</code> in ajax headers
I wish there somebody help me with this code. I don't know, but the code looks good for me. Here is the code
blade view
<form class="form-main" enctype="multipart/form-data" method="post" id="formbank" >
<div class="field file" data-title="Upload File">
<input type="file" id="myfile" name="myfile" accept="image/*">
<label for="myfile"><i class="fa fa-upload"></i> <span id="file-title">Select File</span></label>
</div>
<div class="field" data-title="Action">
<button class="but-main">Submit</button>
</div>
</form>
JS script
$(document).ready(function(e){
$('#formbank').on('submit',function(e){
e.preventDefault();
var fd = new FormData(this);
fd.append('myfile',$('#myfile')[0].files[0]);
$.ajax({
async: true,
type:'post',
data:fd,
contentType: false,
cache:false,
processData: false,
headers: {
'X-CSRF-TOKEN' : "{{ csrf_token() }}"
},
url: "{{ route('post.bank') }}",
success:function(data){
console.log(data);
},
error:function(data){
console.log(data);
}
});
});
});
post.bank controller
public function createBank(Request $request){
if ($request->hasFile('myfile')) {
$file = $request->file('myfile');
return $file->getClientOriginalName();
}
else {
$text = 'empty';
return $text;
}
In this case, I only try to return name of uploaded file. Here is the result.
https://drive.google.com/file/d/1zK5YmO8f8cGR110X-oi2bTVMiaMCXYi9/view?usp=sharing "result"

Thank you for all suggestion. Many thanks. After several trial and errors, I find a trick to resolve it by calling main function with setTimeOut(). And i put _token validation in controller. When token is empty, it will return a value that let setTimeOut() do the rest of time until token is loaded correctly.
I guess that way is suited for me. And I will be happy if there is a better answer to resolve it in a better way. Thank you anyway..

Related

Joomla sending Data (special Image) with Ajax (Formdata)

Using Joomla:
My problem is when I submit the button, ajax send an empty data array back to my client. Debbuging in the console shows me that datas in the header but the preview and response values are empty.
Here is my code (I am using a modal form from bootstrap).
HTML in my default script:
<form action="<?php echo JRoute::_('index.php?option=com_addproduct&view=addproducts'); ?>" method="post" name="modalMessageForm" id="modalMessageForm" enctype="multipart/form-data">
<input type="file" id="message-image-upload" accept="image/*" style="display:none;" name="message-image-upload">
<textarea class="form-control message-textarea" id="message-textarea" placeholder="Nachricht..." name="new-message" rows="4"></textarea>
<button type="button" id="button-close-message" class="btn btn-default btn-block btn-message-close" style="display:none; margin-top:5px;"><?=JText::_( 'COM_ADDPRODUCT_MODAL_MESSAGES_CLOSE')?></button>
</form>
JQuery / Ajax:
$(document).on("submit", "#modalMessageForm", function(e)
{
var form = $('#modalMessageForm').get(0);
e.preventDefault();
var formData = new FormData(form);
for(var pair of formData.entries()) {
console.log(pair[0]+ ', '+ pair[1]);
}
$.ajax({
crossDomain: true,
type: "POST",
url: "index.php?option=com_addproduct&task=sendMessages&format=json",
data: formData,
dataType: "json",
processData: false
})
.done(function(data, textStatus, jqXHR){
console.log('Message: '+data.new-message+' PicName: '+data.img);
})
});
Here my controller.php:
public function sendMessages()
{
JResponse::setHeader('Content-Type', 'application/json', true);
$app = JFactory::getApplication();
$input = $app->input;
$new-message = $input->getString('new-message', '', 'RAW');
$img = $_FILES['message-image-upload']["name"];
$img = JFile::makeSafe($img);
$results=array(
'new-message' => 'new-message',
'img' => $img
);
echo json_encode($results);
$app->close();
}
I got the datas / variables in the console log.
it is:
new-message: null,
img: null
trying to set contentType: false will give me an 500 error.
Thank you very much
That´s the info from my network
enter image description here
I figure something out.
It´s the URL in my ajax command.
When I am using a normal url like
url: 'upload.php'
that will work and then I can set the
contentType: false,
But this is not safety enought.
I just want to use this url
url: "index.php?option=com_addproduct&task=sendMessages&format=json",
But then I got the error message that the view is not found. That´s very strange.

File Data is blank array in server side: Laravel 5.3

I am trying to post File using JQuery. Below is my code.
<script language="javascript">
$(document).ready(function() {
$('#frmUpdateProfile').on("submit", function(event) {
event.stopPropagation(); // Stop stuff happening
event.preventDefault(); // Totally stop stuff happening
var data = {
"FileName" : event.target.FileName.files,
"_token" : "{!! csrf_token() !!}"
};
$.ajax({
url: '{{URL::route("UpdateProfile")}}',
method: "POST",
async: true,
data: JSON.stringify(data),
processData: false,
contentType: "application/json; charset=utf-8",
success: function (msg) {
SuccessCallback(msg);
},
error: function (jqXHR) {
ErrorCallback(jqXHR);
}
});
});
});
</script>
I tried processData: false,. While debugging in Js, you can check that image is coming in the data. Below is the screenshot.
But when I print the request data in Laravel, it show blank array.
Html form is here
<form method="POST"
action="http://localhost:1234/AS6-Code/public/UpdateProfile"
accept-charset="UTF-8"
enctype="multipart/form-data"
id="frmUpdateProfile">
<input name="_token" type="hidden" value="26KWkWdNqe5iOFE8VRBf1dRnL5xKxwN25jg3tAFW">
<input type="hidden" name="_token" value="26KWkWdNqe5iOFE8VRBf1dRnL5xKxwN25jg3tAFW">
<input multiple="1" name="FileName" type="file">
<input class="btn btn-info" type="submit" value="Update">
</form>
Am I doing something wrong?
Try sending your request with FormData instead:
var data = new FormData($('#frmUpdateProfile')[0]);
Also set contentType to false:
contentType: false
Also Update
event.target.FileName.files
to
event.target.FileName.files[0]
event.target.FileName.files is a FileList object. I believe you need event.target.FileName.files[0] instead.

ajax request to controller to update view in laravel

I can't find a working solution for this problem:
I want to update a part of my view without reloading it,
I have a form that collects the data to be passed to the controller,
the controller needs to get the data from the DB and spit out a JSON
to the view so that it can be filled with such data.
I tried to adapt this http://tutsnare.com/post-data-using-ajax-in-laravel-5/ but it's not working at all. The data collected is not reaching the controller.
My uderstanding is the javascript part in the view should listen to the click event and send a GET request to the controller, the controller checks if the data is sent through AJAX, gets the data from DB then returns the response in JSON form, the view is then updated.
Please, does anyone have a working example or can explain?
Simple working example using JQuery:
In you routes.php file:
Route::post('/postform', function () {
// here you should do whatever you need to do with posted data
return response()->json(['msg' => 'Success!','test' => Input::get('test')]);
});
and in your blade view file:
<form method="POST" action="{{ url('postform') }}">
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<input type="text" name="test" value="" />
<input type="submit" value="Send" />
</form>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript">
jQuery(function ($) {
$(document).ready(function()
{
var form = $('form');
form.submit(function(e){
e.preventDefault();
$.ajax({
url: form.prop('action'),
type: 'post',
dataType: 'json',
data: form.serialize(),
success: function(data)
{
console.log(data);
if(data.msg){
alert( data.msg + ' You said: ' + data.test);
}
}
})
});
});
});
</script>
As you can see, most of the logic is done in JavaScript which has nothing to do with Laravel. So if that is not understandable for you, I'd recommend to look for jQuery ajax tutorials or rtfm :)
I have experienced submitting a modal form without reloading the entire page. I let the user add option to the dropdown and then repopulate the items on that dropdown without reloading the entire page after and item is added.
you can have custom route to your controller that handles the process and can be called by javascript and will return json
Route::get('/profiles/create/waterSource',function(){
$data = WaterSource::orderBy('description')->get();
return Response::json($data);
});
then the javascript
<script>
$(document).on('submit', '.myForm-waterSource', function(e) {
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
data: $(this).serialize(),
success: function(html) {
$.get('{{ url('profiles') }}/create/waterSource', function(data) {
console.log(data);
$.each(data, function(index,subCatObj){
if (!$('#waterSource option[value="'+subCatObj.id+'"]').length) {
$('#waterSource').append('<option value="'+subCatObj.id+'">'+subCatObj.description+'</option>');
}
});
$('#myModal-waterSource').modal('hide');
$('#modal-waterSource').val('');
});
}
});
e.preventDefault();
});
</script>
You can view the full tutorial at Creating new Dropdown Option Without Reloading the Page in Laravel 5

Doesn't send the $scope to the html

I started to work in Angular few days ago, and I have a problem that I don't know how to fix.
My website is calling a controller.js and this controller calls to an ajax function. The ajax function sent back a correct response, but I can't see it in the web. Here is the code:
var myApp = angular.module('myapp',[]);
myApp.controller('ResolveProduct', ['$scope', function($scope) {
productInformation = function($scope) {
var something;
$.ajax({
type: "GET",
dataType : "json",
async : true,
url : "/ajax/reference/200-B2",
success : function(data) {
something = data.david;
alert(JSON.stringify(something));
$scope.helper = JSON.stringify(something);
},
complete : function($scope) {
$scope.helper = JSON.stringify(something);
alert($scope.helper);
}
});
};
}]);
This sent me a correct answer, but when I do this in the HTML I don't see the answer. (Even if the alert has all the info)
<div ng-controller="ResolveProduct">
<input ng-model="info"></input> information is: {{ $scope.helper }}
<input type="button" id="commitAction" class="slim-button" value="Resolve" onclick="productInformation('')"/>
</div>
You don't need to call $scope in the html side, so change {{$scope.helper}} to {{helper}}
<div ng-controller="ResolveProduct">
<input ng-model="info"></input> information is: {{ helper }}
<input type="button" id="commitAction" class="slim-button" value="Resolve" onclick="productInformation('')"/>
</div>
Update
You have passed empty values to the $scope from the onclick="productInformation('')" method. So the $scope values are cleared .
Please copy and past my code instead of your code.
Js code
var myApp = angular.module('myapp',[]);
myApp.controller('ResolveProduct', ['$scope', function($scope) {
$scope.productInformation = function()
{
var something;
$.ajax({
type: "GET",
dataType : "json",
async : true,
url : "/ajax/reference/200-B2",
success : function(data){
something = data.david;
alert(JSON.stringify(something));
$scope.helper = JSON.stringify(something);
},
complete : function($scope){
$scope.helper = JSON.stringify(something);
alert($scope.helper);
}
});
};
}]);
Html Code
<div ng-controller="ResolveProduct">
<input ng-model="info"></input> information is: {{ helper }}
<input type="button" id="commitAction" class="slim-button" value="Resolve" **ng-click="productInformation()"**/>
</div>
Also, I have changed onclick to ng-click in your button and assigned the function with $scope in your js side ( see the change productInformation to $scope.productInformation)
You should use {{ helper }} instead of {{ $scope.helper }}.
Also, after $scope.helper = JSON.stringify(something); you should add $scope.$apply().
You need to call $scope.$apply() because you are assigning a value to $scope.helper outside the digest loop (because you are using $.ajax from jQuery).
An explanation for the digest loop in angular can be found here: How do I use $scope.$watch and $scope.$apply in AngularJS?
Please check whether it works
<div ng-controller="ResolveProduct">
<input ng-model="info"></input> information is: {{helper }}
<input type="button" id="commitAction" class="slim-button" value="Resolve" onclick="productInformation('')"/>
</div>
You can't use $scope here
Refer this for help:
http://www.bennadel.com/blog/2457-accessing-scope-on-the-dom-using-angularjs.htm

How to include CSRF from Codeigniter into ajax data

I am trying to pass some data into my Controller, but I'm getting a 500 error. After some research, I discovered that it's caused by the CSRF token not being sent.
It seems like I need to include this along with the data: <?php echo $this->security->get_csrf_token_name(); ?>:"<?php echo $this->security->get_csrf_hash(); ?>"
My JS is pretty weak, so I'm a little confused on how to alter this to include the above.
<script type="text/javascript">
$(document).ready(function() {
$("#order").sortable({
update : function (event, ui) {
order = $('#order').sortable('serialize');
$.ajax({
url: "<?=base_url().'admin/category/update_order'?>",
type: "POST",
data: order,
success: function(response){
console.log(response);
}
});
}
});
}
);
</script>
The token needs to be passed in the data argument of $.ajax.
This should work but see my notes below.
order['<?php echo $this->security->get_csrf_token_name(); ?>'] = '<?php echo $this->security->get_csrf_hash(); ?>';
However, there are a few bad practices going on here. Mainly you should not use PHP in your javascript because this prevents you from being able to access the javascript as a separate file (this is good because browsers will cache it to make your page load faster and consume less bandwidth).
It's better to store the token in your order <form> html like this..
<input type="hidden" name="<?php echo $this->security->get_csrf_token_name(); ?>" value="<?php echo $this->security->get_csrf_hash(); ?>" />
Then it will get serialized with the rest of your form data.
You can also store the URL in the form's action attribute. This will help your script gracefully degrade and also keeps the URL in one place instead of 2.
<form id="order" method="post" action="<?=base_url()?>admin/category/update_order">
In the $.ajax call, use something like this url: $('#order').attr('action'), assuming #order is the actual form id.
CI stores csrf in cookie and you can fetch it from there:
var csrf = $.cookie('csrf_cookie_name');
The downside of this method is that jQuery doesn't natively provide cookie access. So you will need a jquery plugin.
You're correct, just add the CSRF token to your post data. You can use jQuery's $.extend function to merge your order object you already created with the CSRF token data, like this:
$.extend(alerts, {
'<?php echo $this->security->get_csrf_token_name(); ?>' :
'<?php echo $this->security->get_csrf_hash(); ?>' });
Here's a different approach. Simple function in Auth.php that returns the csrf token name and hash in JSON format. Then, in our javascript, make two ajax calls, the first to grab the csrf creds and insert them into hidden form fields, the second to handle our actual form submit.
// place function in Auth.php controller
public function get_csrf()
{
$csrf['csrf_name'] = $this->security->get_csrf_token_name();
$csrf['csrf_token'] = $this->security->get_csrf_hash();
echo json_encode($csrf);
}
// myFunction()
<script type="text/javascript">
function myFunction() {
// first ajax call to grab the csrf name and token
// from our get_csrf() function in Auth.php
$.ajax({
type: "GET",
dataType: 'json',
url: "https://<your_domain>.com/auth/get_csrf", //replace with your domain
success: function (data) {
// assign csrf name and token to variables
csrf_name = data.csrf_name;
csrf_token = data.csrf_token;
// assign field1 and field2 field values to variables
var form_field1 = document.getElementById('field1').value;
var form_field2 = document.getElementById('field2').value;
// insert csrf creds into form
$('#csrftoken').attr('name', csrf_name);
$('#csrftoken').val(csrf_token);
// second ajax call -- this is our form handler
$.ajax({
type: "POST",
url: "https://<your_domain>.com/<your_controller>/<your_function>", //replace with your domain/controller/function
data: {
// ES6 computed property keys are great...
[csrf_name] : csrf_token,
"field1" : form_field1,
"field2" : form_field2
},
success: function(data) {
// handle the return from your form submit
if (data == "ok") {
console.log("Success!");
$("#infoMessage").html("<p>Success</p>").fadeIn(300);
} else {
console.log("Oops!");
$("#infoMessage").html("<p>Oops!</p>");
}
}
});
}
});
}
</script>
// html
<div id="infoMessage"></div>
<form method="post" accept-charset="utf-8">
<input type="hidden" id="csrftoken" name="" value="" />
<label for="field1">Field 1:</label> <br />
<input type="text" name="field1" id="field1" />
<label for="field2">Field 2:</label> <br />
<input type="text" name="field2" id="field2" />
<input type="button" name="submit" value="SUBMIT" onclick="myFunction()" />
</form>
I extend form_helper as MY_form_helper.php to serve csrf tokens to my own form generation code - you could use something similar:
function secure_form() {
$CI =& get_instance();
return '<input type="hidden" name='.$CI->security->get_csrf_token_name().' value='.$CI->security->get_csrf_hash().'>';
}
another solution is to use .serialize():
$.post("user/save", $('#frmUser').serialize(),function(html){
$("#results").html(html);
});
that will find the hidden field that stores the CSRF data.

Resources